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
This commit is contained in:
karliss 2019-04-21 19:30:57 +03:00 committed by Itay Cohen
parent f45badd026
commit f1fa05e647
4 changed files with 66 additions and 36 deletions

View File

@ -519,6 +519,11 @@ void DisassemblerGraphView::drawBlock(QPainter &p, GraphView::GraphBlock &block)
qreal render_height = viewport()->size().height(); 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 // Render node text
auto x = blockX + (2 * charWidth); auto x = blockX + (2 * charWidth);
int y = static_cast<int>(blockY + (2 * charWidth)); int y = static_cast<int>(blockY + (2 * charWidth));
@ -718,7 +723,7 @@ void DisassemblerGraphView::zoom(QPointF mouseRelativePos, double velocity)
auto globalMouse = mouseRelativePos + getViewOffset(); auto globalMouse = mouseRelativePos + getViewOffset();
mouseRelativePos *= getViewScale(); mouseRelativePos *= getViewScale();
qreal newScale = getViewScale() * std::pow(1.25, velocity); qreal newScale = getViewScale() * std::pow(1.25, velocity);
newScale = std::max(newScale, 0.3); newScale = std::max(newScale, 0.05);
mouseRelativePos /= newScale; mouseRelativePos /= newScale;
setViewScale(newScale); setViewScale(newScale);

View File

@ -111,7 +111,6 @@ void GraphGridLayout::CalculateLayout(std::unordered_map<ut64, GraphBlock> &bloc
} }
// Prepare edge routing // Prepare edge routing
//auto &entryb = layoutState.grid_blocks[entry];
int col_count = 1; int col_count = 1;
int row_count = 0; int row_count = 0;
for (const auto &blockIt : layoutState.grid_blocks) { for (const auto &blockIt : layoutState.grid_blocks) {
@ -183,30 +182,30 @@ void GraphGridLayout::CalculateLayout(std::unordered_map<ut64, GraphBlock> &bloc
row_y.assign(row_count, 0); row_y.assign(row_count, 0);
std::vector<int> col_edge_x(col_count + 1); std::vector<int> col_edge_x(col_count + 1);
std::vector<int> row_edge_y(row_count + 1); std::vector<int> row_edge_y(row_count + 1);
int x = layoutConfig.block_horizontal_margin * 2; int x = layoutConfig.block_horizontal_margin;
for (int i = 0; i < col_count; i++) { for (int i = 0; i <= col_count; i++) {
col_edge_x[i] = x; col_edge_x[i] = x;
x += layoutConfig.block_horizontal_margin * col_edge_count[i]; x += layoutConfig.block_horizontal_margin * col_edge_count[i];
col_x[i] = x; if (i < col_count) {
x += col_width[i]; col_x[i] = x;
x += col_width[i];
}
} }
int y = layoutConfig.block_vertical_margin * 2; int y = layoutConfig.block_vertical_margin;
for (int i = 0; i < row_count; i++) { for (int i = 0; i <= row_count; i++) {
row_edge_y[i] = y; 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]) { if (!row_edge_count[i]) {
// prevent 2 blocks being put on top of each other without any space
row_edge_count[i] = 1; row_edge_count[i] = 1;
} }
y += layoutConfig.block_vertical_margin * row_edge_count[i]; y += layoutConfig.block_vertical_margin * row_edge_count[i];
row_y[i] = y; if (i < row_count) {
y += row_height[i]; row_y[i] = y;
y += row_height[i];
}
} }
col_edge_x[col_count] = x; width = x + (layoutConfig.block_horizontal_margin);
row_edge_y[row_count] = y; height = y + (layoutConfig.block_vertical_margin);
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]);
//Compute node positions //Compute node positions
for (auto &blockIt : blocks) { for (auto &blockIt : blocks) {

View File

@ -145,8 +145,7 @@ void GraphView::beginMouseDrag(QMouseEvent *event)
void GraphView::setViewOffset(QPoint offset) void GraphView::setViewOffset(QPoint offset)
{ {
this->offset = offset; setViewOffsetInternal(offset);
emit viewOffsetChanged(offset);
} }
void GraphView::setViewScale(qreal scale) void GraphView::setViewScale(qreal scale)
@ -200,12 +199,11 @@ void GraphView::paintEvent(QPaintEvent *)
#endif #endif
if (!qFuzzyCompare(getCacheDevicePixelRatioF(), getRequiredCacheDevicePixelRatioF()) if (!qFuzzyCompare(getCacheDevicePixelRatioF(), getRequiredCacheDevicePixelRatioF())
|| getCacheSize() != getRequiredCacheSize()) { || getCacheSize() != getRequiredCacheSize()) {
setCacheDirty(); setCacheDirty();
} }
bool cacheWasDirty = cacheDirty; if (cacheDirty) {
if(cacheDirty) {
paintGraphCache(); paintGraphCache();
cacheDirty = false; 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() void GraphView::paintGraphCache()
{ {
#ifndef QT_NO_OPENGL #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_S, GL_CLAMP_TO_EDGE);
gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
resizeTex = true; resizeTex = true;
} else if(cacheSize != viewport()->size()) { } else if (cacheSize != viewport()->size()) {
gl->glBindTexture(GL_TEXTURE_2D, cacheTexture); gl->glBindTexture(GL_TEXTURE_2D, cacheTexture);
resizeTex = true; resizeTex = true;
} }
if (resizeTex) { if (resizeTex) {
cacheSize = viewport()->size(); 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->glGenFramebuffers(1, &cacheFBO);
gl->glBindFramebuffer(GL_FRAMEBUFFER, cacheFBO); gl->glBindFramebuffer(GL_FRAMEBUFFER, cacheFBO);
gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, cacheTexture, 0); 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]); EdgeConfiguration ec = edgeConfiguration(block, &blocks[edge.target]);
QPen pen(ec.color); QPen pen(ec.color);
pen.setWidth(pen.width() / ec.width_scale); pen.setWidth(pen.width() / ec.width_scale);
if (pen.width() * current_scale < 2) {
pen.setWidth(0);
}
p.setPen(pen); p.setPen(pen);
p.setBrush(ec.color); p.setBrush(ec.color);
p.drawPolyline(polyline); p.drawPolyline(polyline);
@ -358,6 +384,7 @@ void GraphView::centerX(bool emitSignal)
{ {
offset.rx() = -((viewport()->width() - width * current_scale) / 2); offset.rx() = -((viewport()->width() - width * current_scale) / 2);
offset.rx() /= current_scale; offset.rx() /= current_scale;
clampViewOffset();
if (emitSignal) { if (emitSignal) {
emit viewOffsetChanged(offset); emit viewOffsetChanged(offset);
} }
@ -367,6 +394,7 @@ void GraphView::centerY(bool emitSignal)
{ {
offset.ry() = -((viewport()->height() - height * current_scale) / 2); offset.ry() = -((viewport()->height() - height * current_scale) / 2);
offset.ry() /= current_scale; offset.ry() /= current_scale;
clampViewOffset();
if (emitSignal) { if (emitSignal) {
emit viewOffsetChanged(offset); emit viewOffsetChanged(offset);
} }
@ -388,8 +416,9 @@ void GraphView::showBlock(GraphBlock *block)
if (height * current_scale <= viewport()->height()) { if (height * current_scale <= viewport()->height()) {
centerY(false); centerY(false);
} else { } else {
offset.ry() = block->y - 30; offset.ry() = block->y - 35 / current_scale;
} }
clampViewOffset();
emit viewOffsetChanged(offset); emit viewOffsetChanged(offset);
blockTransitionedTo(block); blockTransitionedTo(block);
viewport()->update(); viewport()->update();
@ -481,9 +510,7 @@ void GraphView::mousePressEvent(QMouseEvent *event)
void GraphView::mouseMoveEvent(QMouseEvent *event) void GraphView::mouseMoveEvent(QMouseEvent *event)
{ {
if (scroll_mode) { if (scroll_mode) {
offset.rx() += (scroll_base_x - event->x()) / current_scale; addViewOffset(QPoint(scroll_base_x - event->x(), scroll_base_y - event->y()) / current_scale);
offset.ry() += (scroll_base_y - event->y()) / current_scale;
emit viewOffsetChanged(offset);
scroll_base_x = event->x(); scroll_base_x = event->x();
scroll_base_y = event->y(); scroll_base_y = event->y();
viewport()->update(); 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<int>(30.0 / current_scale); const int delta = static_cast<int>(30.0 / current_scale);
int dx = 0, dy = 0; int dx = 0, dy = 0;
@ -529,9 +556,7 @@ void GraphView::keyPressEvent(QKeyEvent* event)
QAbstractScrollArea::keyPressEvent(event); QAbstractScrollArea::keyPressEvent(event);
return; return;
} }
offset.rx() += dx; addViewOffset(QPoint(dx, dy));
offset.ry() += dy;
emit viewOffsetChanged(offset);
viewport()->update(); viewport()->update();
event->accept(); event->accept();
} }
@ -559,11 +584,8 @@ void GraphView::wheelEvent(QWheelEvent *event)
return; return;
} }
QPoint delta = -event->angleDelta(); QPoint delta = -event->angleDelta();
delta /= current_scale; delta /= current_scale;
offset += delta; addViewOffset(delta);
emit viewOffsetChanged(offset);
viewport()->update(); viewport()->update();
event->accept(); event->accept();
} }

View File

@ -91,6 +91,10 @@ protected:
int width = 0; int width = 0;
int height = 0; int height = 0;
void clampViewOffset();
void setViewOffsetInternal(QPoint pos, bool emitSignal = true);
void addViewOffset(QPoint move, bool emitSignal = true);
private: private:
void centerX(bool emitSignal); void centerX(bool emitSignal);
void centerY(bool emitSignal); void centerY(bool emitSignal);