-
Notifications
You must be signed in to change notification settings - Fork 772
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
899 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#include "CompassController.h" | ||
|
||
#include "control/Control.h" | ||
#include "control/layer/LayerController.h" | ||
#include "gui/XournalView.h" | ||
#include "model/Compass.h" | ||
#include "model/GeometryTool.h" | ||
#include "model/Stroke.h" | ||
#include "model/XojPage.h" | ||
|
||
CompassController::CompassController(XojPageView* view, Compass* s): GeometryToolController(view, s) {} | ||
|
||
CompassController::~CompassController() = default; | ||
|
||
auto CompassController::getType() const -> std::string { return "compass"; } | ||
|
||
auto CompassController::posRelToSide(double x, double y) const -> utl::Point<double> { | ||
cairo_matrix_t inv = s->getMatrix(); | ||
cairo_matrix_invert(&inv); | ||
cairo_matrix_transform_point(&inv, &x, &y); | ||
return utl::Point<double>(x, -y); | ||
} | ||
|
||
auto CompassController::isInsideGeometryTool(double x, double y, double border) const -> bool { | ||
const auto p = posRelToSide(x, y); | ||
return std::hypot(p.x, p.y) <= s->getHeight() + border; | ||
} | ||
|
||
auto CompassController::getPointForPos(double a) const -> utl::Point<double> { | ||
cairo_matrix_t matrix = s->getMatrix(); | ||
double x = s->getHeight() * std::cos(a); | ||
double y = s->getHeight() * std::sin(a); | ||
cairo_matrix_transform_point(&matrix, &x, &y); | ||
|
||
return utl::Point<double>(x, y); | ||
} | ||
|
||
void CompassController::createStroke(double a) { | ||
if (!std::isnan(a)) { | ||
angleMax = a; | ||
angleMin = a; | ||
|
||
const auto p = this->getPointForPos(a); | ||
initializeStroke(); | ||
stroke->addPoint(Point(p.x, p.y)); | ||
stroke->addPoint(Point(p.x, p.y)); // doubled point | ||
s->notify(); | ||
} else { | ||
g_warning("No valid stroke from compass!"); | ||
} | ||
} | ||
|
||
void CompassController::updateStroke(double x) { | ||
angleMax = std::max(this->angleMax, x); | ||
angleMin = std::min(this->angleMin, x); | ||
stroke->deletePointsFrom(0); | ||
const auto h = view->getXournal()->getControl()->getToolHandler(); | ||
const auto filled = (h->getFill() != -1); | ||
const auto c = utl::Point{s->getTranslationX(), s->getTranslationY()}; | ||
|
||
if (filled && angleMax < angleMin + 2 * M_PI) { | ||
stroke->addPoint(Point(c.x, c.y)); | ||
} | ||
for (auto i = 0; i <= 100; i++) { | ||
auto p = getPointForPos(angleMin + static_cast<double>(i) / 100.0 * (angleMax - angleMin)); | ||
stroke->addPoint(Point(p.x, p.y)); | ||
} | ||
if (filled && angleMax < angleMin + 2 * M_PI) { | ||
stroke->addPoint(Point(c.x, c.y)); | ||
} | ||
s->notify(); | ||
} | ||
|
||
void CompassController::finalizeStroke() { | ||
angleMax = NAN; | ||
angleMin = NAN; | ||
addStrokeToLayer(); | ||
} | ||
|
||
auto CompassController::existsStroke() -> bool { return !std::isnan(angleMax) && !std::isnan(angleMin); } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/* | ||
* Xournal++ | ||
* | ||
* A Compass controller | ||
* | ||
* @author Xournal++ Team | ||
* https://github.com/xournalpp/xournalpp | ||
* | ||
* @license GNU GPLv2 or later | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <gtk/gtk.h> | ||
|
||
#include "gui/PageView.h" | ||
#include "util/Point.h" | ||
|
||
#include "GeometryToolController.h" | ||
|
||
class Compass; | ||
class Stroke; | ||
|
||
/** | ||
* @brief A class that controls a compass | ||
* The compass can be moved, rotated and scaled | ||
* There are methods for translating coordinates | ||
* and methods to deal with the temporary stroke | ||
* that is displayed near the the outline of the | ||
* compass or a radius. | ||
*/ | ||
|
||
class CompassController: public GeometryToolController { | ||
public: | ||
CompassController(XojPageView* view, Compass* s); | ||
~CompassController(); | ||
|
||
public: | ||
std::string getType() const override; | ||
|
||
/** | ||
* @brief returns the position of a point relative to a coordinate system, in which the | ||
* positive x-axis coincides with the distinguished compass axis and the origin lies | ||
* in the center of the compass | ||
* @param x the x-coordinate of the point (in document coordinates) | ||
* @param y the y-coordinate of the point (in document coordinates) | ||
*/ | ||
utl::Point<double> posRelToSide(double x, double y) const; | ||
|
||
/** | ||
* @brief checks whether a point with given coordinates lies in the geometry tool with an additional | ||
* border enlarging (or shrinked) it | ||
* @param x the x-coordinate of the given point (in document coordinates) | ||
* @param y the y-coordinate of the given point (in document coordinates) | ||
* @param border the size of the border (if negative, the geometry tool is shrinked via the border) | ||
*/ | ||
bool isInsideGeometryTool(double x, double y, double border = 0.0) const override; | ||
|
||
/** | ||
* @brief the point (in document coordinates) for a given angle on the outline of the setsquare | ||
* @param a the angle with respect to the distinguished compass axis of the point | ||
*/ | ||
utl::Point<double> getPointForPos(double a) const; | ||
|
||
/** | ||
* @brief creates a stroke starting at the given angle of the outline of the compass | ||
* @param a the angle of the point on the outline of the compass (when unrotated and untranslated) | ||
*/ | ||
void createStroke(double a); | ||
|
||
/** | ||
* @brief updates the stroke aligned to the outline of the compass | ||
* @param a the angle of the point on the outline of the compass (when unrotated and untranslated) | ||
* updating the stroke | ||
*/ | ||
void updateStroke(double a); | ||
|
||
/** | ||
* @brief finishes the stroke aligned to the outline of the compass | ||
*/ | ||
void finalizeStroke(); | ||
|
||
/** | ||
* checks whether a stroke already exists | ||
*/ | ||
bool existsStroke(); | ||
|
||
private: | ||
/** | ||
* @brief when a stroke near the outline of the compass is drawn, the minimal and maximal | ||
* angles of the point to be drawn (with respect to an unrotated, and untranslated coordinate system) | ||
* are saved in the variables angleMin and angleMax | ||
*/ | ||
double angleMax = NAN; | ||
double angleMin = NAN; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#include "CompassInputHandler.h" | ||
|
||
#include <memory> // for __shared_ptr_access, shar... | ||
|
||
#include "control/CompassController.h" // for CompassController, HYPOTENUSE | ||
#include "control/Control.h" | ||
#include "control/ToolEnums.h" // for TOOL_HAND, TOOL_HIGHLIGHTER | ||
#include "control/ToolHandler.h" // for ToolHandler | ||
#include "gui/XournalView.h" // for XournalView | ||
#include "gui/inputdevices/InputEvents.h" | ||
#include "model/Compass.h" | ||
|
||
constexpr double MIN_HEIGHT = 1.0; | ||
constexpr double MAX_HEIGHT = 10.0; | ||
|
||
CompassInputHandler::CompassInputHandler(XournalView* xournal, GeometryToolController* controller): | ||
GeometryToolHandler(xournal, controller, Compass::INITIAL_HEIGHT, Compass::INITIAL_X, Compass::INITIAL_Y) {} | ||
|
||
CompassInputHandler::~CompassInputHandler() noexcept { this->unregisterFromPool(); } | ||
|
||
auto CompassInputHandler::handlePointer(InputEvent const& event) -> bool { | ||
const auto coords = getCoords(event); | ||
CompassController* compassController = static_cast<CompassController*>(controller); | ||
|
||
const auto toolHandler = xournal->getControl()->getToolHandler(); | ||
switch (toolHandler->getToolType()) { | ||
case TOOL_HIGHLIGHTER: | ||
case TOOL_PEN: | ||
if (event.type == BUTTON_PRESS_EVENT) { | ||
if (controller->isInsideGeometryTool(coords.x, coords.y, 0) && | ||
!controller->isInsideGeometryTool(coords.x, coords.y, -0.5)) { | ||
// initialize range | ||
const auto p = compassController->posRelToSide(coords.x, coords.y); | ||
lastProj = std::atan2(-p.y, p.x); | ||
compassController->createStroke(lastProj); | ||
return true; | ||
} | ||
return false; | ||
} else if (event.type == MOTION_EVENT) { | ||
// update range and paint | ||
if (compassController->existsStroke()) { | ||
const auto p = compassController->posRelToSide(coords.x, coords.y); | ||
auto proj = std::atan2(-p.y, p.x); | ||
proj = lastProj + std::remainder(proj - lastProj, 2 * M_PI); | ||
compassController->updateStroke(proj); | ||
lastProj = proj; | ||
return true; | ||
} | ||
return false; | ||
} else if (event.type == BUTTON_RELEASE_EVENT) { | ||
// add stroke to layer and reset | ||
if (compassController->existsStroke()) { | ||
compassController->finalizeStroke(); | ||
lastProj = NAN; | ||
return true; | ||
} | ||
} | ||
return false; | ||
case TOOL_HAND: | ||
if (event.type == BUTTON_PRESS_EVENT) { | ||
if (!controller->isInsideGeometryTool(coords.x, coords.y, 0)) { | ||
return false; | ||
} else { | ||
sequenceStart(event); | ||
this->handScrolling = true; | ||
return true; | ||
} | ||
} else if (event.type == MOTION_EVENT && this->handScrolling) { | ||
scrollMotion(event); | ||
return true; | ||
} else if (event.type == BUTTON_RELEASE_EVENT && this->handScrolling) { | ||
this->handScrolling = false; | ||
} | ||
default: | ||
return false; | ||
} | ||
} | ||
|
||
auto CompassInputHandler::getMinHeight() const -> double { return MIN_HEIGHT; } | ||
auto CompassInputHandler::getMaxHeight() const -> double { return MAX_HEIGHT; } |
Oops, something went wrong.