#include "controller.h" #include "arbeitsview.h" #include "mainwindow.h" #include "kmath.h" #include #include ArbeitsController *ArbeitsController::controller[ USERMODE_COUNT ]; // gibt den Controller zurück, welcher in einem Bestimmten Modus verwendet // wird // m: der Modus, bei dem der gesuchte Controller benutzt wird ArbeitsController *ArbeitsController::getController( UserMode m ) { return controller[ m ]; } // Erstellt die Controller, welche bei den verschiedenen Modis benutzt // werden sollen // m: Das Modell, welches alle nötigen Daten vür die Arbeitsansicht enthält void ArbeitsController::initStaticController( ArbeitsModel *m ) { controller[ SELECT ] = new HideController( m ); controller[ MOVE ] = new MoveController( m ); controller[ NEW ] = new NewController( m ); controller[ PIPETTE_SELECT ] = new CopyController( m ); controller[ PIPETTE_SET ] = new PasteController( m ); controller[ DELETE ] = new DeleteController( m ); controller[ CUT ] = new CutController( m ); controller[ ZOOM_IN ] = new ZoomInController( m ); } ArbeitsController::ArbeitsController( ArbeitsModel *m ) { model = m; } // Setzt den Controller zurück void ArbeitsController::restartController() { model->notifyViews(); } // verwaltet das drehen des Mausrades void ArbeitsController::wheelEvent(QWheelEvent *e) { if( !model->getFrame() ) return; // Ermitteln der View Größe und der Bildgröße QSize s = model->getViewSize(); QRect imgRect( QPoint( 0, 0 ), s ); QSize imgS = model->getImage().size(); if( imgS.width() > s.width() ) { imgS.scale( s, Qt::KeepAspectRatio ); imgRect.setSize( imgS ); } QPoint bottomRight = model->inverseTranslate( imgRect.bottomRight() ); int xOffset = model->getXOffset(); // Aktualisieren des aus dem Bild angezeigten gebietes int yOffset = model->getYOffset(); xOffset += (int)( e->angleDelta().y() * (imgRect.width() / 500.0) ) / 2; yOffset += (int)( e->angleDelta().y() * (imgRect.height() / 500.0) ) / 2; QPoint nBottomRight( bottomRight.x() - (int)( e->angleDelta().y() * (imgRect.width() / 500.0) ) / 2, bottomRight.y() - (int)( e->angleDelta().y() * (imgRect.height() / 500.0) ) / 2 ); if( e->angleDelta().y() > 0 ) { QPoint center( model->getViewPos().x() + model->getViewSize().width() / 2, model->getViewPos().y() + model->getViewSize().height() / 2 ); QPoint move = e->pos() - center; xOffset += move.x(); yOffset += move.y(); nBottomRight.setX( nBottomRight.x() + move.x() ); nBottomRight.setY( nBottomRight.y() + move.y() ); } if( xOffset < 0 ) { nBottomRight.setX( nBottomRight.x() - xOffset ); xOffset -= xOffset; } if( yOffset < 0 ) { nBottomRight.setY( nBottomRight.y() - yOffset ); yOffset -= yOffset; } if( nBottomRight.x() > model->getImage().width() ) { xOffset -= nBottomRight.x() - model->getImage().width(); nBottomRight.setX( model->getImage().width() ); } if( nBottomRight.y() > model->getImage().height() ) { yOffset -= nBottomRight.y() - model->getImage().height(); nBottomRight.setY( model->getImage().height() ); } if( xOffset >= nBottomRight.x() || yOffset >= nBottomRight.y() ) return; // abbruch // Aktualisieren der Sklallierungsfaktoren if( xOffset < 0 || yOffset < 0 ) { xOffset = 0; yOffset = 0; model->setScaleFactor(imgRect.width() / (float)model->getImage().width(), imgRect.height() / (float)model->getImage().height()); model->notifyViews(); return; } model->setScaleFactor( imgRect.width() / (float)(nBottomRight.x() - xOffset), imgRect.height() / (float)(nBottomRight.y() - yOffset)); model->setOffset( xOffset, yOffset ); model->notifyViews(); } // verwaltet das Drücken einer Maustaste void ArbeitsController::mousePressEvent( QMouseEvent *e ) { model->setMouseButtonPressed( e->button(), e->pos() ); model->notifyViews(); } // verwaltet das Bewegen der Maus void ArbeitsController::mouseMoveEvent( QMouseEvent *e ) { if( model->isMouseButtonPressed( Qt::MidButton ) ) { // Falls die mittlere Masutaste gedrückt ist, kann der nutzer den angezeigten Bereich des Bildes verschieben QPoint diff = e->pos() - model->getMousePoint(); diff = QPoint( (int)(diff.x() / model->getXScaleFactor()) * 5, (int)(diff.y() / model->getYScaleFactor()) * 5 ); if( diff != QPoint( 0, 0 ) ) { QSize s = model->getViewSize(); QRect imgRect( QPoint( 0, 0 ), s ); QSize imgS = model->getImage().size(); if( imgS.width() > s.width() ) { imgS.scale( s, Qt::KeepAspectRatio ); imgRect.setSize( imgS ); } QPoint bottomRight = model->inverseTranslate( imgRect.bottomRight() ); int xOffset = model->getXOffset(), yOffset = model->getYOffset(); bottomRight.setX( bottomRight.x() + diff.x() ); bottomRight.setY( bottomRight.y() + diff.y() ); xOffset += diff.x(); yOffset += diff.y(); if( xOffset < 0 ) { bottomRight.setX( bottomRight.x() - xOffset ); xOffset -= xOffset; } if( yOffset < 0 ) { bottomRight.setY( bottomRight.y() - yOffset ); yOffset -= yOffset; } if( bottomRight.x() > model->getImage().width() ) { xOffset -= bottomRight.x() - model->getImage().width(); bottomRight.setX( model->getImage().width() ); } if( bottomRight.y() > model->getImage().height() ) { yOffset -= bottomRight.y() - model->getImage().height(); bottomRight.setY( model->getImage().height() ); } if( xOffset >= bottomRight.x() || yOffset >= bottomRight.y() ) return; model->setOffset( xOffset, yOffset ); model->notifyViews(); } } model->setMousePoint( e->pos() ); model->notifyViews(); } // verwaltet das Loslassen einer Maustaste void ArbeitsController::mouseReleaseEvent( QMouseEvent *e ) { model->setMousePressed( false ); model->notifyViews(); } /* * Controller für den SELECT Modus */ HideController::HideController( ArbeitsModel *m ) : ArbeitsController( m ) {} void HideController::mouseReleaseEvent( QMouseEvent *e ) { // Verstecken oder sichtbarmachen des Objektes, auf das geklickt wurde if( model->isMouseButtonPressed( Qt::LeftButton ) && e ) { model->getFrame()->selectObjectAt( model->inverseTranslate( e->pos() ) ); model->getWindow()->setFrameTreeSelection(); } ArbeitsController::mouseReleaseEvent( e ); } /* * Controller für den MOVE Modus */ MoveController::MoveController( ArbeitsModel *m ) : ArbeitsController( m ) {} void MoveController::mousePressEvent( QMouseEvent *e ) { // Auswahl des Punktes der verschoben werden soll if( e->button() == Qt::LeftButton && !model->getMoveObject().isNull() && model->getInsertIndex() >= 0 ) { model->getMoveObject()->insertVertex( model->getInsertIndex(), model->getNewVertex(), model->getMovePolygon() ); model->setMoveIndex( model->getInsertIndex() ); model->setInsertIndex( -1 ); } ArbeitsController::mousePressEvent( e ); } void MoveController::mouseMoveEvent( QMouseEvent *e ) { // Verschieben des ausgewählten Punktes und findes des der Maus nächstgelegenen Punktes if( e ) { if( !model->isMousePressed() ) { // findes des der Maus nächstgelegenen Punktes bool foundNp = false; QPoint mousePos = model->inverseTranslate(e->pos()); double mdiff = 0; for( ObjectPolygon obj : model->getFrame()->getObjects() ) { if( obj->isSelected() ) { int pIndex = 0; for( QPolygon o : obj->getPolygonList() ) { QPoint last = o.last(); int index = 0; for( QPoint point : o ) { QPoint tmp = Math::getNearestPointOnLine( mousePos, point, last ); QPoint dir = mousePos - tmp; int tmpDiff = dir.x() * dir.x() + dir.y() * dir.y(); if( !foundNp || tmpDiff < mdiff ) { if( Math::diffSquare( tmp, point ) < 500 ) { model->setMoveObject( obj, pIndex ); model->setMoveIndex( index ); model->setInsertIndex( -1 ); } else if( Math::diffSquare( tmp, last ) < 500 ) { model->setMoveObject( obj, pIndex ); model->setMoveIndex( index - 1 ); model->setInsertIndex( -1 ); if( index - 1 < 0 ) model->setMoveIndex( o.count() - 1 ); } else { model->setMoveObject( obj, pIndex ); model->setInsertIndex( index ); model->setMoveIndex( -1 ); model->setNewVertex( tmp ); } foundNp = true; mdiff = tmpDiff; } last = point; index++; } pIndex++; } } } if( !foundNp || mdiff > 500 ) { model->setInsertIndex( -1 ); model->setMoveIndex( -1 ); } } // move if( model->isMouseButtonPressed( Qt::LeftButton ) && model->getMoveIndex() >= 0 && !model->getMoveObject().isNull() ) { model->getMoveObject()->moveVertex( model->getMoveIndex(), model->inverseTranslate( e->pos() ), model->getImage().size(), model->getMovePolygon() ); } } ArbeitsController::mouseMoveEvent( e ); } /* * Controller für den CUT Modus */ CutController::CutController( ArbeitsModel *m ) : ArbeitsController( m ) {} void CutController::mouseReleaseEvent( QMouseEvent *e ) { if( model->isMouseButtonPressed( Qt::LeftButton ) && e ) { // Auswahl der Punkte an denen das Objekt zerschnitten werden soll QPoint pos = model->inverseTranslate( e->pos() ); QList< ObjectPolygon > objects = model->getFrame()->getObjects(); if( model->getCutObject().isNull() ) { // Auswahl des ersten Punktes for( auto p = objects.begin(); p != objects.end(); p++ ) { int pIndex = 0; for( QPolygon pol : (*p)->getPolygonList() ) { int index = 0; for( QPoint point : pol ) { if( pos.x() > point.x() - 10 && pos.x() < point.x() + 10 && pos.y() > point.y() - 10 && pos.y() < point.y() + 10 ) { model->setCutObject( *p, pIndex ); model->setCutIndex( index ); } index++; } if( !model->getCutObject().isNull() ) break; pIndex++; } } } else { // Auswahl des zweiten Punktes if( !model->getCutObject().isNull() && model->getFrame() ) { int index = 0; foreach( QPoint point, model->getCutObject()->getPolygonList().at( model->getCutPolygon() ) ) { if( pos.x() > point.x() - 10 && pos.x() < point.x() + 10 && pos.y() > point.y() - 10 && pos.y() < point.y() + 10 ) break; index++; } if( index >= model->getCutIndex() - 1 && index <= model->getCutIndex() + 1 ) return; if( ( model->getCutIndex() == 0 && index == model->getCutObject()->getPolygonList().at( model->getCutPolygon() ).size() - 1 ) || ( index == 0 && model->getCutIndex() == model->getCutObject()->getPolygonList().at( model->getCutPolygon() ).size() - 1 ) || index == model->getCutObject()->getPolygonList().at( model->getCutPolygon() ).size() ) return; // Zerschneiden des Objektes an den zwei eckpunkten model->getFrame()->splitObject( model->getCutObject(), model->getCutIndex(), index, model->getCutPolygon() ); model->setCutObject( ObjectPolygon(), 0 ); model->setCutIndex( -1 ); model->getWindow()->setupFrameTree(); } } } ArbeitsController::mouseReleaseEvent( e ); } /* * Controller für den PIPETTE_SELECT Modus */ CopyController::CopyController( ArbeitsModel *m ) : ArbeitsController( m ) {} void CopyController::mouseReleaseEvent( QMouseEvent *e ) { // Auswahl des Objektes, welches kopiert werden soll if( model->isMouseButtonPressed( Qt::LeftButton ) && e ) { if( model->getFrame() ) { int pIndex; model->setCopyedObject( model->getFrame()->getObjectAt( model->inverseTranslate( e->pos() ), pIndex ), model->inverseTranslate( e->pos() ) ); model->setCopyedRotation( 0 ); if( !model->getCopyedObject().isNull() ) model->getWindow()->setMode( PIPETTE_SET ); } } ArbeitsController::mouseReleaseEvent( e ); } /* * Controller für den PIPETTE_SET Modus */ PasteController::PasteController( ArbeitsModel *m ) : ArbeitsController( m ) {} void PasteController::mouseMoveEvent( QMouseEvent *e ) { // Setzen der Position und der Rotierung des kopierten Objektes if( model->isMouseButtonPressed( Qt::RightButton ) ) { if( !model->getCopyedObject().isNull() ) model->setCopyedRotation( model->getCopyedRotation() + e->pos().x() - model->getMousePoint().x() ); } ArbeitsController::mouseMoveEvent( e ); } void PasteController::mouseReleaseEvent( QMouseEvent *e ) { // Einfpgen des Objektes oder der Objekt-ID if( model->isMouseButtonPressed( Qt::LeftButton ) && e ) { if( model->getFrame() ) { model->getFrame()->setObjectAt( model->inverseTranslate( e->pos() ), model->getCopyedObject(), model->getCopyedCenter(), model->getCopyedRotation() ); model->getWindow()->setupFrameTree(); int pIndex; model->setCopyedObject( model->getFrame()->getObjectAt( model->inverseTranslate( e->pos() ), pIndex ), model->inverseTranslate( e->pos() ) ); model->setCopyedRotation( 0 ); } } ArbeitsController::mouseReleaseEvent( e ); } /* * Controller für den NEW Modus */ NewController::NewController( ArbeitsModel *m ) : ArbeitsController( m ) {} void NewController::mouseReleaseEvent( QMouseEvent *e ) { if( model->isMouseButtonPressed( Qt::LeftButton ) && e ) { // Hinzufügen von Punkten zum neuen Polygon if( !model->getNewPolygon() ) model->setNewPolygon( new QPolygon() ); QPoint pos = model->inverseTranslate( e->pos() ); if( model->getNewPolygon()->size() > 3 && pos.x() > model->getNewPolygon()->begin()->x() - 10 && pos.x() < model->getNewPolygon()->begin()->x() + 10 && pos.y() > model->getNewPolygon()->begin()->y() - 10 && pos.y() < model->getNewPolygon()->begin()->y() + 10 ) { // Polygon ist fertig und wird zur Sequenz hinzugefügt QList polygons; polygons.append( *model->getNewPolygon() ); if( model->getFrame() ) model->getFrame()->addObject( "-1", 0, polygons ); model->setNewPolygon( 0 ); model->getWindow()->setupFrameTree(); } else model->getNewPolygon()->append( pos ); } if( model->isMouseButtonPressed( Qt::RightButton ) && e ) { // Letzten Punkt vom Polygon entfernen if( model->getNewPolygon() ) { if( model->getNewPolygon()->size() == 1 ) model->setNewPolygon( 0 ); else model->getNewPolygon()->pop_back(); } } ArbeitsController::mouseReleaseEvent( e ); } void NewController::restartController() { // Neues Polygon beenden und zur Sequenz hinzufügen if( model->getNewPolygon() && model->getNewPolygon()->size() >= 3 ) { QList polygons; polygons.append( *model->getNewPolygon() ); model->getFrame()->addObject( "-1", 0, polygons ); model->setNewPolygon( 0 ); model->getWindow()->setupFrameTree(); ArbeitsController::restartController(); } } /* * Controller für den DELETE Modus */ DeleteController::DeleteController( ArbeitsModel *m ) : ArbeitsController( m ) {} void DeleteController::mousePressEvent( QMouseEvent *e ) { // Setzt den Beginn des auswahl feldes if( e && e->button() == Qt::LeftButton ) { if (!model->getDeleteField() ) model->setDeleteField( new QRect(e->pos(), QSize()) ); } ArbeitsController::mousePressEvent( e ); } void DeleteController::mouseMoveEvent( QMouseEvent *e ) { // Setze das Ende des Auswahl Feldes if( e && model->isMouseButtonPressed( Qt::LeftButton ) && model->getDeleteField() ) { *model->getDeleteField() = QRect( model->getMousePressPoint(), e->pos() ).normalized(); } ArbeitsController::mouseMoveEvent( e ); } void DeleteController::mouseReleaseEvent( QMouseEvent *e ) { // Lösche alle Eckpunkte im ausgewählten Feld if( model->isMouseButtonPressed( Qt::LeftButton ) && e && model->getDeleteField() && model->getFrame() ) { if( model->getDeleteField()->size() == QSize( 0, 0 ) ) model->getFrame()->selectObjectAt( model->inverseTranslate( e->pos() ) ); else { QRect field = *model->getDeleteField(); model->getFrame()->removeSelectedVertices(QRect( model->inverseTranslate( field.topLeft() ), model->inverseTranslate( field.bottomRight() ) )); delete model->getDeleteField(); model->setDeleteField( 0 ); model->getWindow()->setupFrameTree(); } } ArbeitsController::mouseReleaseEvent( e ); } /* * Controller für den ZOOM_IN Modus */ ZoomInController::ZoomInController( ArbeitsModel *m ) : ArbeitsController( m ) {} void ZoomInController::mousePressEvent( QMouseEvent *e ) { // Setzte den Startpunkt des sichtbaren Gebiets if( e->button() == Qt::LeftButton ) { if (!model->getDeleteField() ) model->setDeleteField( new QRect(e->pos(), QSize()) ); } ArbeitsController::mousePressEvent( e ); } void ZoomInController::mouseMoveEvent( QMouseEvent *e ) { // Setzte den Endpunkt des sichtbaren Gebiets if( model->isMouseButtonPressed( Qt::LeftButton ) && model->getDeleteField() && e ) { *model->getDeleteField() = QRect( model->getMousePressPoint(), e->pos() ).normalized(); } ArbeitsController::mouseMoveEvent( e ); } void ZoomInController::mouseReleaseEvent( QMouseEvent *e ) { // Aktualisiere die Ansicht auf das ausgewählte Gebiet if( model->isMouseButtonPressed( Qt::LeftButton ) && e && model->getFrame() && model->getDeleteField() ) { if( model->getDeleteField()->size() == QSize( 0, 0 ) ) model->getFrame()->selectObjectAt( model->inverseTranslate( e->pos() ) ); else { QRect field = *model->getDeleteField(); QPoint leftTop = model->inverseTranslate( field.topLeft() ); int xOffset = leftTop.x(), yOffset = leftTop.y(); if( xOffset < 0 ) xOffset = 0; if( yOffset < 0 ) yOffset = 0; QPoint bottomRight = model->inverseTranslate( field.bottomRight() ); if( bottomRight.x() >= model->getImage().width() ) bottomRight.setX( model->getImage().width() ); if( bottomRight.y() >= model->getImage().height() ) bottomRight.setY( model->getImage().height() ); if( bottomRight.x() > xOffset && bottomRight.y() > yOffset ) { QSize s = model->getViewSize(); QRect imgRect( QPoint( 0, 0 ), s ); QSize imgS = model->getImage().size(); if( imgS.width() > s.width() ) { imgS.scale( s, Qt::KeepAspectRatio ); imgRect.setSize( imgS ); } model->setScaleFactor( imgRect.width() / (float)(bottomRight.x() - xOffset), imgRect.height() / (float)(bottomRight.y() - yOffset)); model->setOffset( xOffset, yOffset ); } delete model->getDeleteField(); model->setDeleteField( 0 ); model->getWindow()->setupFrameTree(); } } ArbeitsController::mouseReleaseEvent( e ); }