Skip to content

Commit

Permalink
Fix custom cursor sizing on HiDPI screens
Browse files Browse the repository at this point in the history
  • Loading branch information
Vanuan committed Jul 23, 2020
1 parent 6ab4bb5 commit fdfda05
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 54 deletions.
157 changes: 104 additions & 53 deletions src/Mod/Sketcher/Gui/DrawSketchHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,77 @@ void DrawSketchHandler::setCursor(const QPixmap &p,int x,int y)
Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer();

oldCursor = viewer->getWidget()->cursor();
QCursor cursor(p, x, y);
QPixmap p1(p);

qreal pRatio = viewer->devicePixelRatio();

int newWidth = p.width()*pRatio;
int newHeight = p.height()*pRatio;
p1 = p1.scaled(newWidth, newHeight,Qt::KeepAspectRatio,Qt::SmoothTransformation);
p1.setDevicePixelRatio(pRatio);

QCursor cursor(p1, x * pRatio, y * pRatio);
actCursor = cursor;

viewer->getWidget()->setCursor(cursor);
}
}

void DrawSketchHandler::addCursorTail( std::vector<QPixmap> &pixmaps ) {
// Create a pixmap that will contain icon and each autoconstraint icon
Gui::MDIView* view = Gui::getMainWindow()->activeWindow();
if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer();
QPixmap baseIcon = QPixmap(actCursor.pixmap());
// cursor size in device independent pixels
qreal pixelRatio = viewer->devicePixelRatio();
qreal baseCursorWidth = baseIcon.width() / pixelRatio;
qreal baseCursorHeight = baseIcon.width() / pixelRatio;


int iconWidth = 16;
int tailWidth = pixmaps.size() * iconWidth;

int newIconWidth = baseCursorWidth + tailWidth;
int newIconHeight = baseCursorHeight;
QPixmap newIcon(newIconWidth, newIconHeight);
newIcon.fill(Qt::transparent);

QPainter qp;
qp.begin(&newIcon);

qp.drawPixmap(0,0, baseIcon);

// Iterate through pixmaps and them to the cursor pixmap
std::vector<QPixmap>::iterator pit=pixmaps.begin();
int i = 0;
qreal currentIconX = baseCursorWidth;
qreal currentIconY;

for (; pit != pixmaps.end(); ++pit, i++) {
QPixmap icon = *pit;
icon = icon.scaledToWidth(iconWidth);
currentIconY = baseCursorHeight - icon.height();
qp.drawPixmap(QPoint(currentIconX, currentIconY), icon);
currentIconX += icon.width();
}

qp.end(); // Finish painting

// Create the new cursor with the icon.
QPoint p=actCursor.hotSpot();

// Scale back to device dependent pixels
qreal newWidth = newIcon.width()*pixelRatio;
qreal newHeight = newIcon.height()*pixelRatio;
newIcon = newIcon.scaled(newWidth, newHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);
newIcon.setDevicePixelRatio(pixelRatio);

QCursor newCursor(newIcon, p.x(), p.y());
applyCursor(newCursor);
}
}

void DrawSketchHandler::applyCursor(void)
{
applyCursor(actCursor);
Expand All @@ -128,6 +192,43 @@ void DrawSketchHandler::unsetCursor(void)
}
}

std::vector<QPixmap> DrawSketchHandler::suggestedConstraintsPixmaps(
std::vector<AutoConstraint> &suggestedConstraints) {
std::vector<QPixmap> pixmaps;
// Iterate through AutoConstraints types and get their pixmaps
std::vector<AutoConstraint>::iterator it=suggestedConstraints.begin();
int i = 0;
for (; it != suggestedConstraints.end(); ++it, i++) {
QString iconType;
switch (it->Type)
{
case Horizontal:
iconType = QString::fromLatin1("Constraint_Horizontal");
break;
case Vertical:
iconType = QString::fromLatin1("Constraint_Vertical");
break;
case Coincident:
iconType = QString::fromLatin1("Constraint_PointOnPoint");
break;
case PointOnObject:
iconType = QString::fromLatin1("Constraint_PointOnObject");
break;
case Tangent:
iconType = QString::fromLatin1("Constraint_Tangent");
break;
default:
break;
}
if (!iconType.isEmpty()) {
QPixmap icon = Gui::BitmapFactory()
.pixmap(iconType.toLatin1());
pixmaps.push_back(icon);
}
}
return pixmaps;
}

int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggestedConstraints,
const Base::Vector2d& Pos, const Base::Vector2d& Dir,
AutoConstraint::TargetType type)
Expand Down Expand Up @@ -502,58 +603,8 @@ void DrawSketchHandler::createAutoConstraints(const std::vector<AutoConstraint>

void DrawSketchHandler::renderSuggestConstraintsCursor(std::vector<AutoConstraint> &suggestedConstraints)
{
// Auto Constraint icon size in px
int iconSize = 16;

// Create a pixmap that will contain icon and each autoconstraint icon
QPixmap baseIcon = actCursor.pixmap();
QPixmap newIcon(baseIcon.width() + suggestedConstraints.size() * iconSize,
baseIcon.height());
newIcon.fill(Qt::transparent);

QPainter qp;
qp.begin(&newIcon);

qp.drawPixmap(0,0, baseIcon);

// Iterate through AutoConstraints type and add icons to the cursor pixmap
std::vector<AutoConstraint>::iterator it=suggestedConstraints.begin();
int i = 0;
for (; it != suggestedConstraints.end(); ++it, i++) {
QString iconType;
switch (it->Type)
{
case Horizontal:
iconType = QString::fromLatin1("Constraint_Horizontal");
break;
case Vertical:
iconType = QString::fromLatin1("Constraint_Vertical");
break;
case Coincident:
iconType = QString::fromLatin1("Constraint_PointOnPoint");
break;
case PointOnObject:
iconType = QString::fromLatin1("Constraint_PointOnObject");
break;
case Tangent:
iconType = QString::fromLatin1("Constraint_Tangent");
break;
default:
break;
}

if (!iconType.isEmpty()) {
QPixmap icon = Gui::BitmapFactory().pixmap(iconType.toLatin1()).scaledToWidth(iconSize);
qp.drawPixmap(QPoint(baseIcon.width() + i * iconSize, baseIcon.height() - iconSize), icon);
}
}

qp.end(); // Finish painting

// Create the new cursor with the icon.
QPoint p=actCursor.hotSpot();
QCursor newCursor(newIcon, p.x(), p.y());
applyCursor(newCursor);
std::vector<QPixmap> pixmaps = suggestedConstraintsPixmaps(suggestedConstraints);
addCursorTail(pixmaps);
}

void DrawSketchHandler::setPositionText(const Base::Vector2d &Pos, const SbString &text)
Expand Down
13 changes: 12 additions & 1 deletion src/Mod/Sketcher/Gui/DrawSketchHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,23 @@ class SketcherGuiExport DrawSketchHandler

protected:
// helpers
void setCursor( const QPixmap &p,int x,int y );
/**
* Sets a cursor for 3D inventor view.
* pixmap as a cursor image in device independent pixels.
**/
void setCursor( const QPixmap &pixmap, int x,int y );
void addCursorTail(std::vector<QPixmap> &pixmaps);
void unsetCursor(void);
void applyCursor(void);
void applyCursor(QCursor &newCursor);
void setCrosshairColor();

/**
* Returns contraints icons scaled to width.
**/
std::vector<QPixmap> suggestedConstraintsPixmaps(
std::vector<AutoConstraint> &suggestedConstraints);

ViewProviderSketch *sketchgui;
QCursor oldCursor;
QCursor actCursor;
Expand Down

0 comments on commit fdfda05

Please sign in to comment.