Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: snap to grid #1013

Merged
merged 22 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2433598
feat: add function to determine snap point and force
letsfindaway Jun 10, 2024
2fe0ec7
feat: snap axes
letsfindaway Jun 10, 2024
098a36f
feat: snap to grid for ruler
letsfindaway Jun 11, 2024
e1a343b
feat: snap to grid for protractor
letsfindaway Jun 11, 2024
94676bf
feat: snap to grid for triangle
letsfindaway Jun 11, 2024
86e85af
feat: snap to grid for compass
letsfindaway Jun 11, 2024
60639b9
feat: snap to grid when drawing line
letsfindaway Jun 11, 2024
e62bc34
feat: snap to grid when moving objects
letsfindaway Jun 12, 2024
2e0fdb7
feat: snap to grid on delegate resize
letsfindaway Jun 13, 2024
2e8acf5
feat: snap to grid on delegate move
letsfindaway Jun 15, 2024
519cede
fix: snap unselected strokes using pointer tool
letsfindaway Aug 17, 2024
412202e
feat: snap object rotation with shift only
letsfindaway Aug 19, 2024
5f9d962
feat: display snap indicator when moving objects
letsfindaway Aug 19, 2024
3f0a903
feat: snap to grid for multiselection group
letsfindaway Aug 22, 2024
2a36a36
feat: stepwise rotation of items
letsfindaway Aug 23, 2024
68eb432
feat: snap angle while drawing line
letsfindaway Aug 23, 2024
319f809
feat: snap angle on multiselection rotation
letsfindaway Aug 23, 2024
8164c20
feat: snap rotation angle of ruler
letsfindaway Sep 6, 2024
9dc6a2a
feat: snap rotation angle of protractor
letsfindaway Sep 6, 2024
335a326
feat: snap rotation angle of triangle
letsfindaway Sep 6, 2024
65794e9
feat: snap rotation angle of compass
letsfindaway Sep 6, 2024
619227f
feat: for a plain background, snap as for a grid
letsfindaway Sep 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion resources/etc/OpenBoard.config
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
[App]
AngleTolerance=4
HideCheckForSoftwareUpdate=false
HideSwapDisplayScreens=true
EnableAutomaticSoftwareUpdates=true
Expand All @@ -12,6 +11,7 @@ LastSessionPageIndex=0
PageCacheSize=20
PreferredLanguage=fr_CH
ProductWebAddress=http://www.openboard.ch
RotationAngleStep=5.
RunInWindow=false
SoftwareUpdateURL=http://www.openboard.ch/update.json
StartMode=
Expand Down
27 changes: 20 additions & 7 deletions src/board/UBBoardController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,35 +299,48 @@ void UBBoardController::setBoxing(QRect displayRect)
}
}

void UBBoardController::setCursorFromAngle(QString angle)
void UBBoardController::setCursorFromAngle(QString angle, const QPoint offset)
{
QWidget *controlViewport = controlView()->viewport();

QSize cursorSize(45,30);
QSize bitmapSize = cursorSize;
int hotX = -1;
int hotY = -1;

QImage mask_img(cursorSize, QImage::Format_Mono);
if (!offset.isNull())
{
bitmapSize.setWidth(std::max(bitmapSize.width(), 2 * std::abs(offset.x())));
bitmapSize.setHeight(std::max(bitmapSize.height(), 2 * std::abs(offset.y())));
hotX = bitmapSize.width() / 2 - offset.x();
hotY = bitmapSize.height() / 2 - offset.y();
}

QSize origin = (bitmapSize - cursorSize) / 2;

QImage mask_img(bitmapSize, QImage::Format_Mono);
mask_img.fill(0xff);
QPainter mask_ptr(&mask_img);
mask_ptr.setBrush( QBrush( QColor(0, 0, 0) ) );
mask_ptr.drawRoundedRect(0,0, cursorSize.width()-1, cursorSize.height()-1, 6, 6);
mask_ptr.drawRoundedRect(origin.width(), origin.height(), cursorSize.width()-1, cursorSize.height()-1, 6, 6);
QBitmap bmpMask = QBitmap::fromImage(mask_img);


QPixmap pixCursor(cursorSize);
QPixmap pixCursor(bitmapSize);
pixCursor.fill(QColor(Qt::white));

QPainter painter(&pixCursor);

painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.setBrush(QBrush(Qt::white));
painter.setPen(QPen(QColor(Qt::black)));
painter.drawRoundedRect(1,1,cursorSize.width()-2,cursorSize.height()-2,6,6);
painter.drawRoundedRect(origin.width() + 1, origin.height() + 1,cursorSize.width()-2,cursorSize.height()-2,6,6);
painter.setFont(QFont("Arial", 10));
painter.drawText(1,1,cursorSize.width(),cursorSize.height(), Qt::AlignCenter, angle.append(QChar(176)));
painter.drawText(origin.width() + 1, origin.height() + 1,cursorSize.width(),cursorSize.height(), Qt::AlignCenter, angle.append(QChar(176)));
painter.end();

pixCursor.setMask(bmpMask);
controlViewport->setCursor(QCursor(pixCursor));
controlViewport->setCursor(QCursor(pixCursor, hotX, hotY));
}


Expand Down
2 changes: 1 addition & 1 deletion src/board/UBBoardController.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class UBBoardController : public UBDocumentContainer
void persistCurrentScene(bool isAnAutomaticBackup = false, bool forceImmediateSave = false);
void showNewVersionAvailable(bool automatic, const UBVersion &installedVersion, const UBSoftwareUpdate &softwareUpdate);
void setBoxing(QRect displayRect);
void setCursorFromAngle(QString angle);
void setCursorFromAngle(QString angle, const QPoint offset = {});
void setToolbarTexts();
static QUrl expandWidgetToTempDir(const QByteArray& pZipedData, const QString& pExtension = QString("wgt"));

Expand Down
57 changes: 46 additions & 11 deletions src/board/UBBoardView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include "gui/UBToolWidget.h"
#include "gui/UBResources.h"
#include "gui/UBMainWindow.h"
#include "gui/UBSnapIndicator.h"
#include "gui/UBThumbnailWidget.h"

#include "board/UBBoardController.h"
Expand Down Expand Up @@ -391,13 +392,13 @@ void UBBoardView::tabletEvent (QTabletEvent * event)
switch (event->type ()) {
case QEvent::TabletPress: {
mTabletStylusIsPressed = true;
scene()->inputDevicePress (scenePos, pressure);
scene()->inputDevicePress (scenePos, pressure, event->modifiers());

break;
}
case QEvent::TabletMove: {
if (mTabletStylusIsPressed)
scene ()->inputDeviceMove (scenePos, pressure);
scene ()->inputDeviceMove (scenePos, pressure, event->modifiers());

acceptEvent = false; // rerouted to mouse move

Expand All @@ -409,7 +410,7 @@ void UBBoardView::tabletEvent (QTabletEvent * event)
scene ()->setToolCursor (currentTool);
setToolCursor (currentTool);

scene ()->inputDeviceRelease ();
scene ()->inputDeviceRelease (currentTool, event->modifiers());

mPendingStylusReleaseEvent = false;

Expand Down Expand Up @@ -693,9 +694,9 @@ bool UBBoardView::itemShouldBeMoved(QGraphicsItem *item)
case UBGraphicsMediaItem::Type:
case UBGraphicsVideoItem::Type:
case UBGraphicsAudioItem::Type:
case UBGraphicsStrokesGroup::Type:
return true;

case UBGraphicsStrokesGroup::Type:
case UBGraphicsTextItem::Type:
if (currentTool == UBStylusTool::Play)
return true;
Expand Down Expand Up @@ -842,9 +843,32 @@ void UBBoardView::handleItemMouseMove(QMouseEvent *event)
if (getMovingItem() && itemShouldBeMoved(getMovingItem()) && (mMouseButtonIsPressed || mTabletStylusIsPressed))
{
QPointF scenePos = mapToScene(event->pos());
QPointF newPos = getMovingItem()->pos() + scenePos - mLastPressedMousePos;
getMovingItem()->setPos(newPos);
mLastPressedMousePos = scenePos;
auto movingItem = getMovingItem();
QPointF newPos = movingItem->pos() + scenePos - mLastPressedMousePos;
movingItem->setPos(newPos);

// snap to grid
if (event->modifiers().testFlag(Qt::ShiftModifier))
{
QRectF rect = UBGraphicsScene::itemRect(movingItem);
Qt::Corner corner;
auto offset = scene()->snap(rect, &corner);
newPos += offset;
movingItem->setPos(newPos);

mLastPressedMousePos = scenePos + offset;

// display snap indicator
if (!offset.isNull())
{
updateSnapIndicator(corner);
}
}
else
{
mLastPressedMousePos = scenePos;
}

mWidgetMoved = true;
event->accept();
}
Expand Down Expand Up @@ -924,6 +948,17 @@ void UBBoardView::setMultiselection(bool enable)
mMultipleSelectionIsEnabled = enable;
}

void UBBoardView::updateSnapIndicator(Qt::Corner corner)
{
if (!mSnapIndicator)
{
mSnapIndicator = new UBSnapIndicator(this);
mSnapIndicator->resize(60, 60);
}

mSnapIndicator->appear(corner);
}

void UBBoardView::setBoxing(const QMargins& margins)
{
mMargins = margins;
Expand Down Expand Up @@ -1052,7 +1087,7 @@ void UBBoardView::mousePressEvent (QMouseEvent *event)
return;
}

setMultiselection(event->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier));
setMultiselection(event->modifiers() & Qt::ControlModifier);

#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
QPointF eventPosition = event->position();
Expand Down Expand Up @@ -1146,7 +1181,7 @@ void UBBoardView::mousePressEvent (QMouseEvent *event)
connect(&mLongPressTimer, SIGNAL(timeout()), this, SLOT(longPressEvent()));
mLongPressTimer.start();
}
scene()->inputDevicePress(mapToScene(UBGeometryUtils::pointConstrainedInRect(event->pos(), rect())));
scene()->inputDevicePress(mapToScene(UBGeometryUtils::pointConstrainedInRect(event->pos(), rect())), 1., event->modifiers());
}
event->accept ();
}
Expand Down Expand Up @@ -1311,7 +1346,7 @@ void UBBoardView::mouseMoveEvent (QMouseEvent *event)

default:
if (!mTabletStylusIsPressed && scene()) {
scene()->inputDeviceMove(mapToScene(UBGeometryUtils::pointConstrainedInRect(event->pos(), rect())) , mMouseButtonIsPressed);
scene()->inputDeviceMove(mapToScene(UBGeometryUtils::pointConstrainedInRect(event->pos(), rect())) , mMouseButtonIsPressed, event->modifiers());
}
event->accept ();
}
Expand All @@ -1333,7 +1368,7 @@ void UBBoardView::mouseReleaseEvent (QMouseEvent *event)
setToolCursor (currentTool);
// first/ propagate device release to the scene
if (scene())
scene()->inputDeviceRelease();
scene()->inputDeviceRelease(currentTool, event->modifiers());

#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
QPointF eventPosition = event->position();
Expand Down
3 changes: 3 additions & 0 deletions src/board/UBBoardView.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class UBBoardController;
class UBGraphicsScene;
class UBGraphicsWidgetItem;
class UBRubberBand;
class UBSnapIndicator;

class UBBoardView : public QGraphicsView
{
Expand All @@ -66,6 +67,7 @@ class UBBoardView : public QGraphicsView
bool isMultipleSelectionEnabled() { return mMultipleSelectionIsEnabled; }

void setBoxing(const QMargins& margins);
void updateSnapIndicator(Qt::Corner corner);

// work around for handling tablet events on MAC OS with Qt 4.8.0 and above
#if defined(Q_OS_OSX)
Expand Down Expand Up @@ -208,6 +210,7 @@ class UBBoardView : public QGraphicsView
bool mRubberBandInPlayMode;

QMargins mMargins{};
UBSnapIndicator* mSnapIndicator{nullptr};

static bool hasSelectedParents(QGraphicsItem * item);

Expand Down
2 changes: 1 addition & 1 deletion src/core/UBSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ void UBSettings::init()
KeyboardLocale = new UBSetting(this, "Board", "StartupKeyboardLocale", 0);
swapControlAndDisplayScreens = new UBSetting(this, "App", "SwapControlAndDisplayScreens", false);

angleTolerance = new UBSetting(this, "App", "AngleTolerance", 4);
rotationAngleStep = new UBSetting(this, "App", "RotationAngleStep", 5.);
historyLimit = new UBSetting(this, "Web", "HistoryLimit", 15);

libIconSize = new UBSetting(this, "Library", "LibIconSize", defaultLibraryIconSize);
Expand Down
2 changes: 1 addition & 1 deletion src/core/UBSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ class UBSettings : public QObject
UBSetting* KeyboardLocale;
UBSetting* swapControlAndDisplayScreens;

UBSetting* angleTolerance;
UBSetting* rotationAngleStep;
UBSetting* historyLimit;

UBSetting* libIconSize;
Expand Down
Loading