You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

159 lines
3.3 KiB

#include "EraseHandler.h"
#include "control/jobs/RenderJob.h"
#include "control/ToolHandler.h"
#include "gui/PageView.h"
#include "gui/XournalView.h"
#include "model/Document.h"
#include "model/eraser/EraseableStroke.h"
#include "model/Layer.h"
#include "model/Stroke.h"
#include "undo/EraseUndoAction.h"
#include "undo/DeleteUndoAction.h"
#include "undo/UndoRedoHandler.h"
#include <Range.h>
#include <Rectangle.h>
#include <cmath>
EraseHandler::EraseHandler(UndoRedoHandler* undo, Document* doc, PageRef page, ToolHandler* handler, Redrawable* view)
{
XOJ_INIT_TYPE(EraseHandler);
this->page = page;
this->handler = handler;
this->view = view;
this->doc = doc;
this->eraseDeleteUndoAction = NULL;
this->eraseUndoAction = NULL;
this->undo = undo;
this->halfEraserSize = 0;
}
EraseHandler::~EraseHandler()
{
XOJ_CHECK_TYPE(EraseHandler);
if (this->eraseDeleteUndoAction)
{
this->finalize();
}
XOJ_RELEASE_TYPE(EraseHandler);
}
/**
* Handle eraser event: "Delete Stroke" and "Standard", Whiteout is not handled here
*/
void EraseHandler::erase(double x, double y)
{
XOJ_CHECK_TYPE(EraseHandler);
this->halfEraserSize = this->handler->getThickness();
GdkRectangle eraserRect = {
gint(x - halfEraserSize),
gint(y - halfEraserSize),
gint(halfEraserSize * 2),
gint(halfEraserSize * 2)
};
Range* range = new Range(x, y);
Layer* l = page->getSelectedLayer();
vector<Element*> tmp(*l->getElements());
for (Element* e : tmp)
{
if (e->getType() == ELEMENT_STROKE && e->intersectsArea(&eraserRect))
{
eraseStroke(l, (Stroke*) e, x, y, range);
}
}
this->view->rerenderRange(*range);
delete range;
}
void EraseHandler::eraseStroke(Layer* l, Stroke* s, double x, double y, Range* range)
{
XOJ_CHECK_TYPE(EraseHandler);
if (!s->intersects(x, y, halfEraserSize))
{
return;
}
// delete complete element
if (this->handler->getEraserType() == ERASER_TYPE_DELETE_STROKE)
{
this->doc->lock();
int pos = l->removeElement(s, false);
this->doc->unlock();
if (pos == -1)
{
return;
}
range->addPoint(s->getX(), s->getY());
range->addPoint(s->getX() + s->getElementWidth(), s->getY() + s->getElementHeight());
//removed the if statement - this prevents us from putting multiple elements into a
//stroke erase operation, but it also prevents the crashing and layer issues!
if (!this->eraseDeleteUndoAction)
{
this->eraseDeleteUndoAction = new DeleteUndoAction(this->page, true);
this->undo->addUndoAction(this->eraseDeleteUndoAction);
}
this->eraseDeleteUndoAction->addElement(l, s, pos);
}
else // Default eraser
{
int pos = l->indexOf(s);
if (pos == -1)
{
return;
}
if (eraseUndoAction == NULL)
{
eraseUndoAction = new EraseUndoAction(this->page);
this->undo->addUndoAction(eraseUndoAction);
}
EraseableStroke* eraseable = NULL;
if (s->getEraseable() == NULL)
{
doc->lock();
eraseable = new EraseableStroke(s);
s->setEraseable(eraseable);
doc->unlock();
eraseUndoAction->addOriginal(l, s, pos);
}
else
{
eraseable = s->getEraseable();
}
eraseable->erase(x, y, halfEraserSize, range);
}
}
void EraseHandler::finalize()
{
XOJ_CHECK_TYPE(EraseHandler);
if (this->eraseUndoAction)
{
this->eraseUndoAction->finalize();
this->eraseUndoAction = NULL;
}
else if (this->eraseDeleteUndoAction)
{
this->eraseDeleteUndoAction = NULL;
}
}