From f1fa05e647034dce21a54896d7cac70263ff1f04 Mon Sep 17 00:00:00 2001 From: karliss Date: Sun, 21 Apr 2019 19:30:57 +0300 Subject: [PATCH] Help not getting lost in empty parts of graph. (#1467) * Limit how far outside image view can be moved * Allow using main view as overview by zooming out * Fix showBlock position calculation when zoomed out --- src/widgets/DisassemblerGraphView.cpp | 7 +++- src/widgets/GraphGridLayout.cpp | 31 +++++++------- src/widgets/GraphView.cpp | 60 ++++++++++++++++++--------- src/widgets/GraphView.h | 4 ++ 4 files changed, 66 insertions(+), 36 deletions(-) diff --git a/src/widgets/DisassemblerGraphView.cpp b/src/widgets/DisassemblerGraphView.cpp index 827ca2b8..0cbc746b 100644 --- a/src/widgets/DisassemblerGraphView.cpp +++ b/src/widgets/DisassemblerGraphView.cpp @@ -519,6 +519,11 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block) qreal render_height = viewport()->size().height(); + // Stop rendering text when it's too small + if (charHeight * getViewScale() * p.device()->devicePixelRatioF() < 4) { + return; + } + // Render node text auto x = blockX + (2 * charWidth); int y = static_cast(blockY + (2 * charWidth)); @@ -718,7 +723,7 @@ void DisassemblerGraphView::zoom(QPointF mouseRelativePos, double velocity) auto globalMouse = mouseRelativePos + getViewOffset(); mouseRelativePos *= getViewScale(); qreal newScale = getViewScale() * std::pow(1.25, velocity); - newScale = std::max(newScale, 0.3); + newScale = std::max(newScale, 0.05); mouseRelativePos /= newScale; setViewScale(newScale); diff --git a/src/widgets/GraphGridLayout.cpp b/src/widgets/GraphGridLayout.cpp index 69606f87..f06cb843 100644 --- a/src/widgets/GraphGridLayout.cpp +++ b/src/widgets/GraphGridLayout.cpp @@ -111,7 +111,6 @@ void GraphGridLayout::CalculateLayout(std::unordered_map &bloc } // Prepare edge routing - //auto &entryb = layoutState.grid_blocks[entry]; int col_count = 1; int row_count = 0; for (const auto &blockIt : layoutState.grid_blocks) { @@ -183,30 +182,30 @@ void GraphGridLayout::CalculateLayout(std::unordered_map &bloc row_y.assign(row_count, 0); std::vector col_edge_x(col_count + 1); std::vector row_edge_y(row_count + 1); - int x = layoutConfig.block_horizontal_margin * 2; - for (int i = 0; i < col_count; i++) { + int x = layoutConfig.block_horizontal_margin; + for (int i = 0; i <= col_count; i++) { col_edge_x[i] = x; x += layoutConfig.block_horizontal_margin * col_edge_count[i]; - col_x[i] = x; - x += col_width[i]; + if (i < col_count) { + col_x[i] = x; + x += col_width[i]; + } } - int y = layoutConfig.block_vertical_margin * 2; - for (int i = 0; i < row_count; i++) { + int y = layoutConfig.block_vertical_margin; + for (int i = 0; i <= row_count; i++) { row_edge_y[i] = y; - // TODO: The 1 when row_edge_count is 0 is not needed on the original.. not sure why it's required for us if (!row_edge_count[i]) { + // prevent 2 blocks being put on top of each other without any space row_edge_count[i] = 1; } y += layoutConfig.block_vertical_margin * row_edge_count[i]; - row_y[i] = y; - y += row_height[i]; + if (i < row_count) { + row_y[i] = y; + y += row_height[i]; + } } - col_edge_x[col_count] = x; - row_edge_y[row_count] = y; - width = x + (layoutConfig.block_horizontal_margin * 2) + (layoutConfig.block_horizontal_margin * - col_edge_count[col_count]); - height = y + (layoutConfig.block_vertical_margin * 2) + (layoutConfig.block_vertical_margin * - row_edge_count[row_count]); + width = x + (layoutConfig.block_horizontal_margin); + height = y + (layoutConfig.block_vertical_margin); //Compute node positions for (auto &blockIt : blocks) { diff --git a/src/widgets/GraphView.cpp b/src/widgets/GraphView.cpp index 18e99b7b..ece27a02 100644 --- a/src/widgets/GraphView.cpp +++ b/src/widgets/GraphView.cpp @@ -145,8 +145,7 @@ void GraphView::beginMouseDrag(QMouseEvent *event) void GraphView::setViewOffset(QPoint offset) { - this->offset = offset; - emit viewOffsetChanged(offset); + setViewOffsetInternal(offset); } void GraphView::setViewScale(qreal scale) @@ -200,12 +199,11 @@ void GraphView::paintEvent(QPaintEvent *) #endif if (!qFuzzyCompare(getCacheDevicePixelRatioF(), getRequiredCacheDevicePixelRatioF()) - || getCacheSize() != getRequiredCacheSize()) { + || getCacheSize() != getRequiredCacheSize()) { setCacheDirty(); } - bool cacheWasDirty = cacheDirty; - if(cacheDirty) { + if (cacheDirty) { paintGraphCache(); cacheDirty = false; } @@ -228,6 +226,30 @@ void GraphView::paintEvent(QPaintEvent *) } } +void GraphView::clampViewOffset() +{ + const qreal edgeFraction = 0.25; + qreal edgeX = edgeFraction * (viewport()->width() / current_scale); + qreal edgeY = edgeFraction * (viewport()->height() / current_scale); + offset.rx() = std::max(std::min(qreal(offset.x()), width - edgeX), + - viewport()->width() / current_scale + edgeX); + offset.ry() = std::max(std::min(qreal(offset.y()), height - edgeY), + - viewport()->height() / current_scale + edgeY); +} + +void GraphView::setViewOffsetInternal(QPoint pos, bool emitSignal) +{ + offset = pos; + clampViewOffset(); + if (emitSignal) + emit viewOffsetChanged(offset); +} + +void GraphView::addViewOffset(QPoint move, bool emitSignal) +{ + setViewOffsetInternal(offset + move, emitSignal); +} + void GraphView::paintGraphCache() { #ifndef QT_NO_OPENGL @@ -248,13 +270,14 @@ void GraphView::paintGraphCache() gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); resizeTex = true; - } else if(cacheSize != viewport()->size()) { + } else if (cacheSize != viewport()->size()) { gl->glBindTexture(GL_TEXTURE_2D, cacheTexture); resizeTex = true; } if (resizeTex) { cacheSize = viewport()->size(); - gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, viewport()->width(), viewport()->height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, viewport()->width(), viewport()->height(), 0, GL_RGBA, + GL_UNSIGNED_BYTE, nullptr); gl->glGenFramebuffers(1, &cacheFBO); gl->glBindFramebuffer(GL_FRAMEBUFFER, cacheFBO); gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cacheTexture, 0); @@ -314,6 +337,9 @@ void GraphView::paintGraphCache() EdgeConfiguration ec = edgeConfiguration(block, &blocks[edge.target]); QPen pen(ec.color); pen.setWidth(pen.width() / ec.width_scale); + if (pen.width() * current_scale < 2) { + pen.setWidth(0); + } p.setPen(pen); p.setBrush(ec.color); p.drawPolyline(polyline); @@ -358,6 +384,7 @@ void GraphView::centerX(bool emitSignal) { offset.rx() = -((viewport()->width() - width * current_scale) / 2); offset.rx() /= current_scale; + clampViewOffset(); if (emitSignal) { emit viewOffsetChanged(offset); } @@ -367,6 +394,7 @@ void GraphView::centerY(bool emitSignal) { offset.ry() = -((viewport()->height() - height * current_scale) / 2); offset.ry() /= current_scale; + clampViewOffset(); if (emitSignal) { emit viewOffsetChanged(offset); } @@ -388,8 +416,9 @@ void GraphView::showBlock(GraphBlock *block) if (height * current_scale <= viewport()->height()) { centerY(false); } else { - offset.ry() = block->y - 30; + offset.ry() = block->y - 35 / current_scale; } + clampViewOffset(); emit viewOffsetChanged(offset); blockTransitionedTo(block); viewport()->update(); @@ -481,9 +510,7 @@ void GraphView::mousePressEvent(QMouseEvent *event) void GraphView::mouseMoveEvent(QMouseEvent *event) { if (scroll_mode) { - offset.rx() += (scroll_base_x - event->x()) / current_scale; - offset.ry() += (scroll_base_y - event->y()) / current_scale; - emit viewOffsetChanged(offset); + addViewOffset(QPoint(scroll_base_x - event->x(), scroll_base_y - event->y()) / current_scale); scroll_base_x = event->x(); scroll_base_y = event->y(); viewport()->update(); @@ -508,7 +535,7 @@ void GraphView::mouseDoubleClickEvent(QMouseEvent *event) } } -void GraphView::keyPressEvent(QKeyEvent* event) +void GraphView::keyPressEvent(QKeyEvent *event) { const int delta = static_cast(30.0 / current_scale); int dx = 0, dy = 0; @@ -529,9 +556,7 @@ void GraphView::keyPressEvent(QKeyEvent* event) QAbstractScrollArea::keyPressEvent(event); return; } - offset.rx() += dx; - offset.ry() += dy; - emit viewOffsetChanged(offset); + addViewOffset(QPoint(dx, dy)); viewport()->update(); event->accept(); } @@ -559,11 +584,8 @@ void GraphView::wheelEvent(QWheelEvent *event) return; } QPoint delta = -event->angleDelta(); - delta /= current_scale; - offset += delta; - emit viewOffsetChanged(offset); - + addViewOffset(delta); viewport()->update(); event->accept(); } diff --git a/src/widgets/GraphView.h b/src/widgets/GraphView.h index e1c46967..08497f63 100644 --- a/src/widgets/GraphView.h +++ b/src/widgets/GraphView.h @@ -91,6 +91,10 @@ protected: int width = 0; int height = 0; + void clampViewOffset(); + void setViewOffsetInternal(QPoint pos, bool emitSignal = true); + void addViewOffset(QPoint move, bool emitSignal = true); + private: void centerX(bool emitSignal); void centerY(bool emitSignal);