Core/Sketcher: Create ToolHandler class in core for core reuse accross other wbs.
This commit is contained in:
@@ -1217,6 +1217,7 @@ SET(FreeCADGui_CPP_SRCS
|
||||
ManualAlignment.cpp
|
||||
StartupProcess.cpp
|
||||
TransactionObject.cpp
|
||||
ToolHandler.cpp
|
||||
)
|
||||
SET(FreeCADGui_SRCS
|
||||
Application.h
|
||||
@@ -1254,6 +1255,7 @@ SET(FreeCADGui_SRCS
|
||||
ManualAlignment.h
|
||||
StartupProcess.h
|
||||
TransactionObject.h
|
||||
ToolHandler.h
|
||||
${FreeCADGui_SDK_MOC_HDRS}
|
||||
)
|
||||
|
||||
|
||||
299
src/Gui/ToolHandler.cpp
Normal file
299
src/Gui/ToolHandler.cpp
Normal file
@@ -0,0 +1,299 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Pierre-Louis Boyer <development@ondsel.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <cmath>
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QPainter>
|
||||
|
||||
#include <Inventor/events/SoKeyboardEvent.h>
|
||||
#endif // #ifndef _PreComp_
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Exception.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "BitmapFactory.h"
|
||||
#include "CommandT.h"
|
||||
#include "MainWindow.h"
|
||||
#include "View3DInventor.h"
|
||||
#include "View3DInventorViewer.h"
|
||||
|
||||
#include "ToolHandler.h"
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
/**************************** ToolHandler *******************************************/
|
||||
ToolHandler::ToolHandler()
|
||||
{}
|
||||
|
||||
ToolHandler::~ToolHandler()
|
||||
{}
|
||||
|
||||
QString ToolHandler::getCrosshairCursorSVGName() const
|
||||
{
|
||||
return QString::fromLatin1("None");
|
||||
}
|
||||
|
||||
bool ToolHandler::activate()
|
||||
{
|
||||
// save the cursor at the time the DSH is activated
|
||||
QWidget* cw = getCursorWidget();
|
||||
if (cw) {
|
||||
oldCursor = cw->cursor();
|
||||
|
||||
updateCursor();
|
||||
|
||||
this->preActivated();
|
||||
this->activated();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ToolHandler::deactivate()
|
||||
{
|
||||
this->deactivated();
|
||||
this->postDeactivated();
|
||||
|
||||
unsetCursor();
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// Helpers
|
||||
|
||||
unsigned long ToolHandler::getCrosshairColor()
|
||||
{
|
||||
unsigned long color = 0xFFFFFFFF; // white
|
||||
ParameterGrp::handle hGrp =
|
||||
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
|
||||
color = hGrp->GetUnsigned("CursorCrosshairColor", color);
|
||||
// from rgba to rgb
|
||||
color = (color >> 8) & 0xFFFFFF;
|
||||
return color;
|
||||
}
|
||||
|
||||
void ToolHandler::setCrosshairCursor(const QString& svgName)
|
||||
{
|
||||
const unsigned long defaultCrosshairColor = 0xFFFFFF;
|
||||
unsigned long color = getCrosshairColor();
|
||||
auto colorMapping = std::map<unsigned long, unsigned long>();
|
||||
colorMapping[defaultCrosshairColor] = color;
|
||||
// hot spot of all SVG icons should be 8,8 for 32x32 size (16x16 for 64x64)
|
||||
int hotX = 8;
|
||||
int hotY = 8;
|
||||
setSvgCursor(svgName, hotX, hotY, colorMapping);
|
||||
}
|
||||
|
||||
void ToolHandler::setCrosshairCursor(const char* svgName)
|
||||
{
|
||||
QString cursorName = QString::fromLatin1(svgName);
|
||||
setCrosshairCursor(cursorName);
|
||||
}
|
||||
|
||||
void ToolHandler::setSvgCursor(const QString& cursorName,
|
||||
int x,
|
||||
int y,
|
||||
const std::map<unsigned long, unsigned long>& colorMapping)
|
||||
{
|
||||
// The TechDraw_Pointer_*.svg icons have a default size of 64x64. When directly creating
|
||||
// them with a size of 32x32 they look very bad.
|
||||
// As a workaround the icons are created with 64x64 and afterwards the pixmap is scaled to
|
||||
// 32x32. This workaround is only needed if pRatio is equal to 1.0
|
||||
//
|
||||
qreal pRatio = devicePixelRatio();
|
||||
bool isRatioOne = (pRatio == 1.0);
|
||||
qreal defaultCursorSize = isRatioOne ? 64 : 32;
|
||||
qreal hotX = x;
|
||||
qreal hotY = y;
|
||||
#if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC)
|
||||
if (qGuiApp->platformName() == QLatin1String("xcb")) {
|
||||
hotX *= pRatio;
|
||||
hotY *= pRatio;
|
||||
}
|
||||
#endif
|
||||
qreal cursorSize = defaultCursorSize * pRatio;
|
||||
|
||||
QPixmap pointer = Gui::BitmapFactory().pixmapFromSvg(cursorName.toStdString().c_str(),
|
||||
QSizeF(cursorSize, cursorSize),
|
||||
colorMapping);
|
||||
if (isRatioOne) {
|
||||
pointer = pointer.scaled(32, 32);
|
||||
}
|
||||
pointer.setDevicePixelRatio(pRatio);
|
||||
setCursor(pointer, hotX, hotY, false);
|
||||
}
|
||||
|
||||
void ToolHandler::setCursor(const QPixmap& p, int x, int y, bool autoScale)
|
||||
{
|
||||
|
||||
QWidget* cw = getCursorWidget();
|
||||
if (cw) {
|
||||
QCursor cursor;
|
||||
QPixmap p1(p);
|
||||
// TODO remove autoScale after all cursors are SVG-based
|
||||
if (autoScale) {
|
||||
qreal pRatio = devicePixelRatio();
|
||||
int newWidth = p.width() * pRatio;
|
||||
int newHeight = p.height() * pRatio;
|
||||
p1 = p1.scaled(newWidth, newHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
p1.setDevicePixelRatio(pRatio);
|
||||
qreal hotX = x;
|
||||
qreal hotY = y;
|
||||
#if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC)
|
||||
if (qGuiApp->platformName() == QLatin1String("xcb")) {
|
||||
hotX *= pRatio;
|
||||
hotY *= pRatio;
|
||||
}
|
||||
#endif
|
||||
cursor = QCursor(p1, hotX, hotY);
|
||||
}
|
||||
else {
|
||||
// already scaled
|
||||
cursor = QCursor(p1, x, y);
|
||||
}
|
||||
|
||||
actCursor = cursor;
|
||||
actCursorPixmap = p1;
|
||||
|
||||
setWidgetCursor(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolHandler::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())) {
|
||||
QPixmap baseIcon = QPixmap(actCursorPixmap);
|
||||
baseIcon.setDevicePixelRatio(actCursorPixmap.devicePixelRatio());
|
||||
qreal pixelRatio = baseIcon.devicePixelRatio();
|
||||
// cursor size in device independent pixels
|
||||
qreal baseCursorWidth = baseIcon.width();
|
||||
qreal baseCursorHeight = baseIcon.height();
|
||||
|
||||
int tailWidth = 0;
|
||||
for (auto const& p : pixmaps) {
|
||||
tailWidth += p.width();
|
||||
}
|
||||
|
||||
int newIconWidth = baseCursorWidth + tailWidth;
|
||||
int newIconHeight = baseCursorHeight;
|
||||
|
||||
QPixmap newIcon(newIconWidth, newIconHeight);
|
||||
newIcon.fill(Qt::transparent);
|
||||
|
||||
QPainter qp;
|
||||
qp.begin(&newIcon);
|
||||
|
||||
qp.drawPixmap(QPointF(0, 0),
|
||||
baseIcon.scaled(baseCursorWidth * pixelRatio,
|
||||
baseCursorHeight * pixelRatio,
|
||||
Qt::KeepAspectRatio,
|
||||
Qt::SmoothTransformation));
|
||||
|
||||
// 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;
|
||||
currentIconY = baseCursorHeight - icon.height();
|
||||
qp.drawPixmap(QPointF(currentIconX, currentIconY), icon);
|
||||
currentIconX += icon.width();
|
||||
}
|
||||
|
||||
qp.end(); // Finish painting
|
||||
|
||||
// Create the new cursor with the icon.
|
||||
QPoint p = actCursor.hotSpot();
|
||||
newIcon.setDevicePixelRatio(pixelRatio);
|
||||
QCursor newCursor(newIcon, p.x(), p.y());
|
||||
applyCursor(newCursor);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolHandler::updateCursor()
|
||||
{
|
||||
auto cursorstring = getCrosshairCursorSVGName();
|
||||
|
||||
if (cursorstring != QString::fromLatin1("None")) {
|
||||
setCrosshairCursor(cursorstring);
|
||||
}
|
||||
}
|
||||
|
||||
void ToolHandler::applyCursor()
|
||||
{
|
||||
applyCursor(actCursor);
|
||||
}
|
||||
|
||||
void ToolHandler::applyCursor(QCursor& newCursor)
|
||||
{
|
||||
setWidgetCursor(newCursor);
|
||||
}
|
||||
|
||||
void ToolHandler::unsetCursor()
|
||||
{
|
||||
setWidgetCursor(oldCursor);
|
||||
}
|
||||
|
||||
qreal ToolHandler::devicePixelRatio()
|
||||
{
|
||||
qreal pixelRatio = 1;
|
||||
|
||||
QWidget* cw = getCursorWidget();
|
||||
if (cw) {
|
||||
pixelRatio = cw->devicePixelRatio();
|
||||
}
|
||||
return pixelRatio;
|
||||
}
|
||||
|
||||
QWidget* ToolHandler::getCursorWidget()
|
||||
{
|
||||
Gui::View3DInventorViewer* viewer = getViewer();
|
||||
if (viewer) {
|
||||
return viewer->getWidget();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ToolHandler::setWidgetCursor(QCursor cursor)
|
||||
{
|
||||
QWidget* cw = getCursorWidget();
|
||||
if (cw) {
|
||||
cw->setCursor(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
Gui::View3DInventorViewer* ToolHandler::getViewer()
|
||||
{
|
||||
Gui::MDIView* view = Gui::getMainWindow()->activeWindow();
|
||||
if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
|
||||
return static_cast<Gui::View3DInventor*>(view)->getViewer();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
127
src/Gui/ToolHandler.h
Normal file
127
src/Gui/ToolHandler.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Pierre-Louis Boyer <development@ondsel.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef GUI_ToolHandler_H
|
||||
#define GUI_ToolHandler_H
|
||||
|
||||
#include <QCursor>
|
||||
#include <QPixmap>
|
||||
|
||||
#include <Base/Parameter.h>
|
||||
#include <Base/Tools2D.h>
|
||||
|
||||
#include "Selection.h"
|
||||
|
||||
|
||||
namespace Gui
|
||||
{
|
||||
class View3DInventorViewer;
|
||||
|
||||
|
||||
class GuiExport ToolHandler
|
||||
{
|
||||
public:
|
||||
ToolHandler();
|
||||
virtual ~ToolHandler();
|
||||
|
||||
bool activate();
|
||||
virtual void deactivate();
|
||||
|
||||
virtual void quit()
|
||||
{}
|
||||
|
||||
/// updates the actCursor with the icon by calling getCrosshairCursorSVGName(),
|
||||
/// enabling to set data member dependent icons (i.e. for different construction methods)
|
||||
void updateCursor();
|
||||
|
||||
private: // NVI
|
||||
virtual void preActivated()
|
||||
{}
|
||||
virtual void activated()
|
||||
{}
|
||||
virtual void deactivated()
|
||||
{}
|
||||
virtual void postDeactivated()
|
||||
{}
|
||||
|
||||
protected: // NVI requiring base implementation
|
||||
virtual QString getCrosshairCursorSVGName() const;
|
||||
|
||||
|
||||
protected:
|
||||
// helpers
|
||||
/**
|
||||
* Sets a cursor for 3D inventor view.
|
||||
* pixmap as a cursor image in device independent pixels.
|
||||
*
|
||||
* \param autoScale - set this to false if pixmap already scaled for HiDPI
|
||||
**/
|
||||
|
||||
/** @name Icon helpers */
|
||||
//@{
|
||||
void setCursor(const QPixmap& pixmap, int x, int y, bool autoScale = true);
|
||||
|
||||
|
||||
void unsetCursor();
|
||||
|
||||
/// restitutes the DSH cached cursor (without any tail due to autoconstraints, ...)
|
||||
void applyCursor();
|
||||
|
||||
void addCursorTail(std::vector<QPixmap>& pixmaps);
|
||||
|
||||
/// returns the color to be used for the crosshair (configurable as a parameter)
|
||||
unsigned long getCrosshairColor();
|
||||
|
||||
/// functions to set the cursor to a given svgName (to be migrated to NVI style)
|
||||
|
||||
qreal devicePixelRatio();
|
||||
//@}
|
||||
|
||||
View3DInventorViewer* getViewer();
|
||||
|
||||
virtual QWidget* getCursorWidget();
|
||||
|
||||
virtual void setWidgetCursor(QCursor cursor);
|
||||
|
||||
private:
|
||||
void setSvgCursor(const QString& svgName, int x, int y,
|
||||
const std::map<unsigned long, unsigned long>& colorMapping =
|
||||
std::map<unsigned long, unsigned long>());
|
||||
|
||||
|
||||
void applyCursor(QCursor& newCursor);
|
||||
|
||||
void setCrosshairCursor(const QString& svgName);
|
||||
void setCrosshairCursor(const char* svgName);
|
||||
|
||||
protected:
|
||||
|
||||
QCursor oldCursor;
|
||||
QCursor actCursor;
|
||||
QPixmap actCursorPixmap;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Gui
|
||||
|
||||
|
||||
#endif // GUI_ToolHandler_H
|
||||
@@ -270,7 +270,8 @@ void CurveConverter::OnChange(Base::Subject<const char*>& rCaller, const char* s
|
||||
// Construction/Destruction
|
||||
|
||||
DrawSketchHandler::DrawSketchHandler()
|
||||
: sketchgui(nullptr)
|
||||
: Gui::ToolHandler()
|
||||
, sketchgui(nullptr)
|
||||
{}
|
||||
|
||||
DrawSketchHandler::~DrawSketchHandler()
|
||||
@@ -281,11 +282,6 @@ std::string DrawSketchHandler::getToolName() const
|
||||
return "DSH_None";
|
||||
}
|
||||
|
||||
QString DrawSketchHandler::getCrosshairCursorSVGName() const
|
||||
{
|
||||
return QString::fromLatin1("None");
|
||||
}
|
||||
|
||||
std::unique_ptr<QWidget> DrawSketchHandler::createWidget() const
|
||||
{
|
||||
return nullptr;
|
||||
@@ -311,36 +307,20 @@ void DrawSketchHandler::activate(ViewProviderSketch* vp)
|
||||
{
|
||||
sketchgui = vp;
|
||||
|
||||
// save the cursor at the time the DSH is activated
|
||||
auto* view = dynamic_cast<Gui::View3DInventor*>(Gui::getMainWindow()->activeWindow());
|
||||
|
||||
if (view) {
|
||||
Gui::View3DInventorViewer* viewer = dynamic_cast<Gui::View3DInventor*>(view)->getViewer();
|
||||
oldCursor = viewer->getWidget()->cursor();
|
||||
|
||||
updateCursor();
|
||||
|
||||
this->signalToolChanged();
|
||||
|
||||
this->preActivated();
|
||||
this->activated();
|
||||
}
|
||||
else {
|
||||
if (!Gui::ToolHandler::activate()) {
|
||||
sketchgui->purgeHandler();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawSketchHandler::deactivate()
|
||||
{
|
||||
this->deactivated();
|
||||
this->postDeactivated();
|
||||
Gui::ToolHandler::deactivate();
|
||||
ViewProviderSketchDrawSketchHandlerAttorney::setConstraintSelectability(*sketchgui, true);
|
||||
|
||||
// clear temporary Curve and Markers from the scenograph
|
||||
clearEdit();
|
||||
clearEditMarkers();
|
||||
resetPositionText();
|
||||
unsetCursor();
|
||||
setAngleSnapping(false);
|
||||
|
||||
ViewProviderSketchDrawSketchHandlerAttorney::signalToolChanged(*sketchgui, "DSH_None");
|
||||
@@ -348,25 +328,10 @@ void DrawSketchHandler::deactivate()
|
||||
|
||||
void DrawSketchHandler::preActivated()
|
||||
{
|
||||
this->signalToolChanged();
|
||||
ViewProviderSketchDrawSketchHandlerAttorney::setConstraintSelectability(*sketchgui, false);
|
||||
}
|
||||
|
||||
void DrawSketchHandler::quit()
|
||||
{
|
||||
assert(sketchgui);
|
||||
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
Gui::Selection().rmvPreselect();
|
||||
|
||||
sketchgui->purgeHandler();
|
||||
}
|
||||
|
||||
void DrawSketchHandler::toolWidgetChanged(QWidget* newwidget)
|
||||
{
|
||||
toolwidget = newwidget;
|
||||
onWidgetChanged();
|
||||
}
|
||||
|
||||
void DrawSketchHandler::registerPressedKey(bool pressed, int key)
|
||||
{
|
||||
// the default behaviour is to quit - specific handler categories may
|
||||
@@ -383,6 +348,23 @@ void DrawSketchHandler::pressRightButton(Base::Vector2d /*onSketchPos*/)
|
||||
quit();
|
||||
}
|
||||
|
||||
|
||||
void DrawSketchHandler::quit()
|
||||
{
|
||||
assert(sketchgui);
|
||||
|
||||
Gui::Selection().rmvSelectionGate();
|
||||
Gui::Selection().rmvPreselect();
|
||||
|
||||
sketchgui->purgeHandler();
|
||||
}
|
||||
|
||||
void DrawSketchHandler::toolWidgetChanged(QWidget* newwidget)
|
||||
{
|
||||
toolwidget = newwidget;
|
||||
onWidgetChanged();
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
// Helpers
|
||||
|
||||
@@ -396,198 +378,6 @@ int DrawSketchHandler::getHighestCurveIndex()
|
||||
return sketchgui->getSketchObject()->getHighestCurveIndex();
|
||||
}
|
||||
|
||||
unsigned long DrawSketchHandler::getCrosshairColor()
|
||||
{
|
||||
unsigned long color = 0xFFFFFFFF; // white
|
||||
ParameterGrp::handle hGrp =
|
||||
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
|
||||
color = hGrp->GetUnsigned("CursorCrosshairColor", color);
|
||||
// from rgba to rgb
|
||||
color = (color >> 8) & 0xFFFFFF;
|
||||
return color;
|
||||
}
|
||||
|
||||
void DrawSketchHandler::setCrosshairCursor(const QString& svgName)
|
||||
{
|
||||
const unsigned long defaultCrosshairColor = 0xFFFFFF;
|
||||
unsigned long color = getCrosshairColor();
|
||||
auto colorMapping = std::map<unsigned long, unsigned long>();
|
||||
colorMapping[defaultCrosshairColor] = color;
|
||||
// hot spot of all SVG icons should be 8,8 for 32x32 size (16x16 for 64x64)
|
||||
int hotX = 8;
|
||||
int hotY = 8;
|
||||
setSvgCursor(svgName, hotX, hotY, colorMapping);
|
||||
}
|
||||
|
||||
void DrawSketchHandler::setCrosshairCursor(const char* svgName)
|
||||
{
|
||||
QString cursorName = QString::fromLatin1(svgName);
|
||||
setCrosshairCursor(cursorName);
|
||||
}
|
||||
|
||||
void DrawSketchHandler::setSvgCursor(const QString& cursorName,
|
||||
int x,
|
||||
int y,
|
||||
const std::map<unsigned long, unsigned long>& colorMapping)
|
||||
{
|
||||
// The Sketcher_Pointer_*.svg icons have a default size of 64x64. When directly creating
|
||||
// them with a size of 32x32 they look very bad.
|
||||
// As a workaround the icons are created with 64x64 and afterwards the pixmap is scaled to
|
||||
// 32x32. This workaround is only needed if pRatio is equal to 1.0
|
||||
//
|
||||
qreal pRatio = devicePixelRatio();
|
||||
bool isRatioOne = (pRatio == 1.0);
|
||||
qreal defaultCursorSize = isRatioOne ? 64 : 32;
|
||||
qreal hotX = x;
|
||||
qreal hotY = y;
|
||||
#if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC)
|
||||
if (qGuiApp->platformName() == QLatin1String("xcb")) {
|
||||
hotX *= pRatio;
|
||||
hotY *= pRatio;
|
||||
}
|
||||
#endif
|
||||
qreal cursorSize = defaultCursorSize * pRatio;
|
||||
|
||||
QPixmap pointer = Gui::BitmapFactory().pixmapFromSvg(cursorName.toStdString().c_str(),
|
||||
QSizeF(cursorSize, cursorSize),
|
||||
colorMapping);
|
||||
if (isRatioOne) {
|
||||
pointer = pointer.scaled(32, 32);
|
||||
}
|
||||
pointer.setDevicePixelRatio(pRatio);
|
||||
setCursor(pointer, hotX, hotY, false);
|
||||
}
|
||||
|
||||
void DrawSketchHandler::setCursor(const QPixmap& p, int x, int y, bool autoScale)
|
||||
{
|
||||
Gui::View3DInventorViewer* viewer = getViewer();
|
||||
if (viewer) {
|
||||
QCursor cursor;
|
||||
QPixmap p1(p);
|
||||
// TODO remove autoScale after all cursors are SVG-based
|
||||
if (autoScale) {
|
||||
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);
|
||||
qreal hotX = x;
|
||||
qreal hotY = y;
|
||||
#if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC)
|
||||
if (qGuiApp->platformName() == QLatin1String("xcb")) {
|
||||
hotX *= pRatio;
|
||||
hotY *= pRatio;
|
||||
}
|
||||
#endif
|
||||
cursor = QCursor(p1, hotX, hotY);
|
||||
}
|
||||
else {
|
||||
// already scaled
|
||||
cursor = QCursor(p1, x, y);
|
||||
}
|
||||
|
||||
actCursor = cursor;
|
||||
actCursorPixmap = p1;
|
||||
|
||||
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())) {
|
||||
QPixmap baseIcon = QPixmap(actCursorPixmap);
|
||||
baseIcon.setDevicePixelRatio(actCursorPixmap.devicePixelRatio());
|
||||
qreal pixelRatio = baseIcon.devicePixelRatio();
|
||||
// cursor size in device independent pixels
|
||||
qreal baseCursorWidth = baseIcon.width();
|
||||
qreal baseCursorHeight = baseIcon.height();
|
||||
|
||||
int tailWidth = 0;
|
||||
for (auto const& p : pixmaps) {
|
||||
tailWidth += p.width();
|
||||
}
|
||||
|
||||
int newIconWidth = baseCursorWidth + tailWidth;
|
||||
int newIconHeight = baseCursorHeight;
|
||||
|
||||
QPixmap newIcon(newIconWidth, newIconHeight);
|
||||
newIcon.fill(Qt::transparent);
|
||||
|
||||
QPainter qp;
|
||||
qp.begin(&newIcon);
|
||||
|
||||
qp.drawPixmap(QPointF(0, 0),
|
||||
baseIcon.scaled(baseCursorWidth * pixelRatio,
|
||||
baseCursorHeight * pixelRatio,
|
||||
Qt::KeepAspectRatio,
|
||||
Qt::SmoothTransformation));
|
||||
|
||||
// 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;
|
||||
currentIconY = baseCursorHeight - icon.height();
|
||||
qp.drawPixmap(QPointF(currentIconX, currentIconY), icon);
|
||||
currentIconX += icon.width();
|
||||
}
|
||||
|
||||
qp.end(); // Finish painting
|
||||
|
||||
// Create the new cursor with the icon.
|
||||
QPoint p = actCursor.hotSpot();
|
||||
newIcon.setDevicePixelRatio(pixelRatio);
|
||||
QCursor newCursor(newIcon, p.x(), p.y());
|
||||
applyCursor(newCursor);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawSketchHandler::updateCursor()
|
||||
{
|
||||
auto cursorstring = getCrosshairCursorSVGName();
|
||||
|
||||
if (cursorstring != QString::fromLatin1("None")) {
|
||||
setCrosshairCursor(cursorstring);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawSketchHandler::applyCursor()
|
||||
{
|
||||
applyCursor(actCursor);
|
||||
}
|
||||
|
||||
void DrawSketchHandler::applyCursor(QCursor& newCursor)
|
||||
{
|
||||
Gui::View3DInventorViewer* viewer = getViewer();
|
||||
if (viewer) {
|
||||
viewer->getWidget()->setCursor(newCursor);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawSketchHandler::unsetCursor()
|
||||
{
|
||||
Gui::View3DInventorViewer* viewer = getViewer();
|
||||
if (viewer) {
|
||||
viewer->getWidget()->setCursor(oldCursor);
|
||||
}
|
||||
}
|
||||
|
||||
qreal DrawSketchHandler::devicePixelRatio()
|
||||
{
|
||||
qreal pixelRatio = 1;
|
||||
Gui::View3DInventorViewer* viewer = getViewer();
|
||||
if (viewer) {
|
||||
pixelRatio = viewer->devicePixelRatio();
|
||||
}
|
||||
return pixelRatio;
|
||||
}
|
||||
|
||||
std::vector<QPixmap>
|
||||
DrawSketchHandler::suggestedConstraintsPixmaps(std::vector<AutoConstraint>& suggestedConstraints)
|
||||
{
|
||||
@@ -1284,12 +1074,3 @@ void DrawSketchHandler::signalToolChanged() const
|
||||
{
|
||||
ViewProviderSketchDrawSketchHandlerAttorney::signalToolChanged(*sketchgui, this->getToolName());
|
||||
}
|
||||
|
||||
Gui::View3DInventorViewer* DrawSketchHandler::getViewer()
|
||||
{
|
||||
Gui::MDIView* view = Gui::getMainWindow()->activeWindow();
|
||||
if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
|
||||
return static_cast<Gui::View3DInventor*>(view)->getViewer();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <Base/Parameter.h>
|
||||
#include <Base/Tools2D.h>
|
||||
#include <Gui/Selection.h>
|
||||
#include <Gui/ToolHandler.h>
|
||||
#include <Mod/Part/App/Geometry.h>
|
||||
#include <Mod/Sketcher/App/Constraint.h>
|
||||
|
||||
@@ -137,26 +138,28 @@ private:
|
||||
* implemented in DrawSketchHandler and used from its derived classes by virtue of the inheritance.
|
||||
* This promotes a concentrating the coupling in a single point (and code reuse).
|
||||
*/
|
||||
class SketcherGuiExport DrawSketchHandler
|
||||
class SketcherGuiExport DrawSketchHandler: public Gui::ToolHandler
|
||||
{
|
||||
public:
|
||||
DrawSketchHandler();
|
||||
virtual ~DrawSketchHandler();
|
||||
|
||||
void activate(ViewProviderSketch*);
|
||||
void deactivate();
|
||||
void deactivate() override;
|
||||
|
||||
virtual void mouseMove(Base::Vector2d pos) = 0;
|
||||
virtual bool pressButton(Base::Vector2d pos) = 0;
|
||||
virtual bool releaseButton(Base::Vector2d pos) = 0;
|
||||
|
||||
virtual void registerPressedKey(bool pressed, int key);
|
||||
virtual void pressRightButton(Base::Vector2d pos);
|
||||
|
||||
virtual void mouseMove(Base::Vector2d onSketchPos) = 0;
|
||||
virtual bool pressButton(Base::Vector2d onSketchPos) = 0;
|
||||
virtual bool releaseButton(Base::Vector2d onSketchPos) = 0;
|
||||
virtual bool onSelectionChanged(const Gui::SelectionChanges&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual void registerPressedKey(bool pressed, int key);
|
||||
virtual void pressRightButton(Base::Vector2d onSketchPos);
|
||||
|
||||
virtual void quit();
|
||||
void quit() override;
|
||||
|
||||
friend class ViewProviderSketch;
|
||||
|
||||
@@ -215,19 +218,12 @@ public:
|
||||
//@}
|
||||
|
||||
private: // NVI
|
||||
virtual void preActivated();
|
||||
virtual void activated()
|
||||
{}
|
||||
virtual void deactivated()
|
||||
{}
|
||||
virtual void postDeactivated()
|
||||
{}
|
||||
void preActivated() override;
|
||||
virtual void onWidgetChanged()
|
||||
{}
|
||||
|
||||
protected: // NVI requiring base implementation
|
||||
virtual std::string getToolName() const;
|
||||
virtual QString getCrosshairCursorSVGName() const;
|
||||
|
||||
virtual std::unique_ptr<QWidget> createWidget() const;
|
||||
virtual bool isWidgetVisible() const;
|
||||
@@ -235,37 +231,6 @@ protected: // NVI requiring base implementation
|
||||
virtual QString getToolWidgetText() const;
|
||||
|
||||
protected:
|
||||
// helpers
|
||||
/**
|
||||
* Sets a cursor for 3D inventor view.
|
||||
* pixmap as a cursor image in device independent pixels.
|
||||
*
|
||||
* \param autoScale - set this to false if pixmap already scaled for HiDPI
|
||||
**/
|
||||
|
||||
/** @name Icon helpers */
|
||||
//@{
|
||||
void setCursor(const QPixmap& pixmap, int x, int y, bool autoScale = true);
|
||||
|
||||
/// updates the actCursor with the icon by calling getCrosshairCursorSVGName(),
|
||||
/// enabling to set data member dependent icons (i.e. for different construction methods)
|
||||
void updateCursor();
|
||||
|
||||
/// restitutes the cursor that was in use at the moment of starting the DrawSketchHandler (i.e.
|
||||
/// oldCursor)
|
||||
void unsetCursor();
|
||||
|
||||
/// restitutes the DSH cached cursor (e.g. without any tail due to autoconstraints, ...)
|
||||
void applyCursor();
|
||||
|
||||
/// returns the color to be used for the crosshair (configurable as a parameter)
|
||||
unsigned long getCrosshairColor();
|
||||
|
||||
/// functions to set the cursor to a given svgName (to be migrated to NVI style)
|
||||
|
||||
qreal devicePixelRatio();
|
||||
//@}
|
||||
|
||||
void drawEdit(const std::vector<Base::Vector2d>& EditCurve) const;
|
||||
void drawEdit(const std::list<std::vector<Base::Vector2d>>& list) const;
|
||||
void drawEdit(const std::vector<Part::Geometry*>& geometries) const;
|
||||
@@ -300,22 +265,6 @@ protected:
|
||||
|
||||
void signalToolChanged() const;
|
||||
|
||||
Gui::View3DInventorViewer* getViewer();
|
||||
|
||||
private:
|
||||
void setSvgCursor(const QString& svgName,
|
||||
int x,
|
||||
int y,
|
||||
const std::map<unsigned long, unsigned long>& colorMapping =
|
||||
std::map<unsigned long, unsigned long>());
|
||||
|
||||
void addCursorTail(std::vector<QPixmap>& pixmaps);
|
||||
|
||||
void applyCursor(QCursor& newCursor);
|
||||
|
||||
void setCrosshairCursor(const QString& svgName);
|
||||
void setCrosshairCursor(const char* svgName);
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
@@ -325,9 +274,6 @@ protected:
|
||||
suggestedConstraintsPixmaps(std::vector<AutoConstraint>& suggestedConstraints);
|
||||
|
||||
ViewProviderSketch* sketchgui;
|
||||
QCursor oldCursor;
|
||||
QCursor actCursor;
|
||||
QPixmap actCursorPixmap;
|
||||
|
||||
QWidget* toolwidget;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user