From 5ae89a95397a7fae8e6f5330c42ee5b15785f914 Mon Sep 17 00:00:00 2001 From: abd Date: Tue, 2 Sep 2008 10:15:05 +0000 Subject: [PATCH] Bug #: IPAL20119 Implementation of QtxRubberBand for customization of selection interface in OCC Viewer --- src/OCCViewer/OCCViewer_ViewSketcher.cxx | 103 ++++++-- src/OCCViewer/OCCViewer_ViewSketcher.h | 7 + src/OCCViewer/OCCViewer_ViewWindow.cxx | 43 +++- src/OCCViewer/OCCViewer_ViewWindow.h | 4 +- src/Qtx/Makefile.am | 2 + src/Qtx/QtxRubberBand.cxx | 313 +++++++++++++++++++++++ src/Qtx/QtxRubberBand.h | 89 +++++++ 7 files changed, 519 insertions(+), 42 deletions(-) create mode 100755 src/Qtx/QtxRubberBand.cxx create mode 100755 src/Qtx/QtxRubberBand.h diff --git a/src/OCCViewer/OCCViewer_ViewSketcher.cxx b/src/OCCViewer/OCCViewer_ViewSketcher.cxx index 335603d48..332a93199 100755 --- a/src/OCCViewer/OCCViewer_ViewSketcher.cxx +++ b/src/OCCViewer/OCCViewer_ViewSketcher.cxx @@ -21,6 +21,8 @@ #include "OCCViewer_ViewWindow.h" #include "OCCViewer_ViewPort3d.h" +#include "QtxRubberBand.h" + #include #include #include @@ -201,8 +203,13 @@ void OCCViewer_ViewSketcher::setSketchButton( int b ) *****************************************************************/ OCCViewer_RectSketcher::OCCViewer_RectSketcher( OCCViewer_ViewWindow* vw, int typ ) -: OCCViewer_ViewSketcher( vw, typ ) + : OCCViewer_ViewSketcher( vw, typ ) { + if ( vw ) + { + OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort(); + mypRectRB = new QtxRectRubberBand( avp ); + } } OCCViewer_RectSketcher::~OCCViewer_RectSketcher() @@ -219,6 +226,7 @@ void OCCViewer_RectSketcher::onDeactivate() { delete (QRect*)mypData; mypData = 0; + mypRectRB->clearGeometry(); } bool OCCViewer_RectSketcher::onKey( QKeyEvent* e ) @@ -251,22 +259,35 @@ void OCCViewer_RectSketcher::onMouse( QMouseEvent* e ) void OCCViewer_RectSketcher::onSketch( SketchState state ) { - OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort(); - - QRect* sketchRect = (QRect*)data(); - if ( myButtonState & sketchButton() ) - { - QRect rect( qMin( myStart.x(), myCurr.x() ), qMin( myStart.y(), myCurr.y() ), - qAbs( myStart.x() - myCurr.x() ), qAbs( myStart.y() - myCurr.y() ) ); - QPainter p( avp ); - p.setPen( Qt::white ); - p.setCompositionMode( QPainter::CompositionMode_Xor ); - if ( state != Debut && !sketchRect->isEmpty() ) - p.drawRect( *sketchRect ); - *sketchRect = rect; - if ( !rect.isEmpty() && state != Fin ) - p.drawRect( *sketchRect ); - } + //OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort(); + + if ( mypRectRB ) + { + QRect* sketchRect = (QRect*)data(); + if ( myButtonState & sketchButton() ) + { + QRect rect = QRect( myStart, myCurr ).normalized(); + /*QRect rect( qMin( myStart.x(), myCurr.x() ), qMin( myStart.y(), myCurr.y() ), + qAbs( myStart.x() - myCurr.x() ), qAbs( myStart.y() - myCurr.y() ) ); + QPainter p( avp ); + p.setPen( Qt::white ); + p.setCompositionMode( QPainter::CompositionMode_Xor ); + */ + + //if ( state != Debut && !sketchRect->isEmpty() ) + // p.drawRect( *sketchRect ); + + *sketchRect = rect; + if ( !rect.isEmpty() && state != Fin ) + { + //p.drawRect( *sketchRect ); + mypRectRB->initGeometry( rect ); + mypRectRB->show(); + } + else + mypRectRB->hide(); + } + } if ( state == Fin ) { @@ -284,16 +305,21 @@ OCCViewer_PolygonSketcher::OCCViewer_PolygonSketcher( OCCViewer_ViewWindow* vw, : OCCViewer_ViewSketcher( vw, typ ), myDbl ( false ), myToler ( 5, 5 ), - mypPoints ( 0L ), + //mypPoints ( 0L ), myAddButton ( 0 ), myDelButton ( 0 ) { mySketchButton = Qt::RightButton; + if ( vw ) + { + OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort(); + mypPolyRB = new QtxPolyRubberBand( avp ); + } } OCCViewer_PolygonSketcher::~OCCViewer_PolygonSketcher() { - delete mypPoints; + //delete mypPoints; delete (QPolygon*)mypData; } @@ -301,7 +327,7 @@ void OCCViewer_PolygonSketcher::onActivate() { myDbl = false; mypData = new QPolygon( 0 ); - mypPoints = new QPolygon( 0 ); + //mypPoints = new QPolygon( 0 ); switch ( sketchButton() ) { @@ -323,10 +349,13 @@ void OCCViewer_PolygonSketcher::onActivate() void OCCViewer_PolygonSketcher::onDeactivate() { - delete mypPoints; - mypPoints = 0; + //delete mypPoints; + //mypPoints = 0; delete (QPolygon*)mypData; mypData = 0; + + if ( mypPolyRB ) + mypPolyRB->clearGeometry(); } bool OCCViewer_PolygonSketcher::onKey( QKeyEvent* e ) @@ -436,10 +465,10 @@ void OCCViewer_PolygonSketcher::onMouse( QMouseEvent* e ) void OCCViewer_PolygonSketcher::onSketch( SketchState state ) { - OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort(); + //OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort(); QPolygon* points = (QPolygon*)data(); - QPainter p( avp ); + /*QPainter p( avp ); p.setPen( Qt::white ); p.setCompositionMode( QPainter::CompositionMode_Xor ); if ( state != Debut ) @@ -453,10 +482,32 @@ void OCCViewer_PolygonSketcher::onSketch( SketchState state ) mypPoints->setPoint( points->count(), myCurr ); if ( state != Fin ) p.drawPolyline( *mypPoints ); - } - + }*/ + if ( mypPolyRB ) + { + mypPolyRB->setUpdatesEnabled ( false ); + if ( !mypPolyRB->isVisible() ) + mypPolyRB->show(); + //if ( state != Debut ) + // mypPolyRB->repaint(); + + if ( state != Fin && points->count() ) + mypPolyRB->initGeometry( QPolygon(*points) << myCurr ); + //mypPolyRB->addNode( myCurr ); + + //if ( state != Fin ) + // mypPolyRB->repaint(); + mypPolyRB->setUpdatesEnabled ( true ); + //mypPolyRB->repaint(); + } + if ( state == Fin ) { + if ( mypPolyRB ) + { + mypPolyRB->clearGeometry(); + mypPolyRB->hide(); + } QApplication::syncX(); mypViewWindow->activateSketching( OCCViewer_ViewWindow::NoSketching ); } diff --git a/src/OCCViewer/OCCViewer_ViewSketcher.h b/src/OCCViewer/OCCViewer_ViewSketcher.h index 55430bed3..86af11639 100755 --- a/src/OCCViewer/OCCViewer_ViewSketcher.h +++ b/src/OCCViewer/OCCViewer_ViewSketcher.h @@ -30,6 +30,9 @@ class QKeyEvent; class QMouseEvent; class QPolygon; +class QtxRectRubberBand; +class QtxPolyRubberBand; + #ifdef WNT #pragma warning ( disable:4251 ) #endif @@ -102,6 +105,8 @@ protected: virtual void onSketch( SketchState ); virtual void onActivate(); virtual void onDeactivate(); + private: + QtxRectRubberBand* mypRectRB; }; /*! @@ -132,6 +137,8 @@ private: QPolygon* mypPoints; int myAddButton; int myDelButton; + + QtxPolyRubberBand* mypPolyRB; }; #ifdef WNT diff --git a/src/OCCViewer/OCCViewer_ViewWindow.cxx b/src/OCCViewer/OCCViewer_ViewWindow.cxx index b42f2d796..d79e8e2f1 100755 --- a/src/OCCViewer/OCCViewer_ViewWindow.cxx +++ b/src/OCCViewer/OCCViewer_ViewWindow.cxx @@ -39,12 +39,12 @@ #include #include +#include #include #include #include #include -#include #include #include @@ -891,19 +891,29 @@ void OCCViewer_ViewWindow::resetState() void OCCViewer_ViewWindow::drawRect() { if ( !myRectBand ) { - myRectBand = new QRubberBand( QRubberBand::Rectangle, myViewPort ); -#ifdef WIN32 - myRectBand->setStyle(new QWindowsStyle); -#endif - QPalette palette; - palette.setColor(myRectBand->foregroundRole(), Qt::white); - myRectBand->setPalette(palette); + myRectBand = new QtxRectRubberBand( myViewPort ); + //QPalette palette; + //palette.setColor(myRectBand->foregroundRole(), Qt::white); + //myRectBand->setPalette(palette); } - myRectBand->hide(); - + //myRectBand->hide(); + + myRectBand->setUpdatesEnabled ( false ); QRect aRect = SUIT_Tools::makeRect(myStartX, myStartY, myCurrX, myCurrY); - myRectBand->setGeometry( aRect ); - myRectBand->setVisible( aRect.isValid() ); + myRectBand->initGeometry( aRect ); + + if ( !myRectBand->isVisible() ) + myRectBand->show(); + + myRectBand->setUpdatesEnabled ( true ); + //myRectBand->repaint(); + + //myRectBand->setVisible( aRect.isValid() ); + //if ( myRectBand->isVisible() ) + // myRectBand->repaint(); + //else + // myRectBand->show(); + //myRectBand->repaint(); } /*! @@ -911,8 +921,13 @@ void OCCViewer_ViewWindow::drawRect() */ void OCCViewer_ViewWindow::endDrawRect() { - delete myRectBand; - myRectBand = 0; + //delete myRectBand; + //myRectBand = 0; + if ( myRectBand ) + { + myRectBand->clearGeometry(); + myRectBand->hide(); + } } /*! diff --git a/src/OCCViewer/OCCViewer_ViewWindow.h b/src/OCCViewer/OCCViewer_ViewWindow.h index c13873886..515a2c8a6 100755 --- a/src/OCCViewer/OCCViewer_ViewWindow.h +++ b/src/OCCViewer/OCCViewer_ViewWindow.h @@ -23,7 +23,7 @@ #include "SUIT_ViewWindow.h" #include -class QRubberBand; +class QtxRectRubberBand; class SUIT_Desktop; class OCCViewer_ViewPort3d; class OCCViewer_ViewSketcher; @@ -195,7 +195,7 @@ private: OCCViewer_SetRotationPointDlg* mySetRotationPointDlg; QtxAction* mySetRotationPointAction; - QRubberBand* myRectBand; //!< selection rectangle rubber band + QtxRectRubberBand* myRectBand; //!< selection rectangle rubber band }; #ifdef WIN32 diff --git a/src/Qtx/Makefile.am b/src/Qtx/Makefile.am index d5a34bb89..414630951 100755 --- a/src/Qtx/Makefile.am +++ b/src/Qtx/Makefile.am @@ -60,6 +60,7 @@ salomeinclude_HEADERS= \ QtxPopupMgr.h \ QtxPreferenceMgr.h \ QtxResourceMgr.h \ + QtxRubberBand.h \ QtxSearchTool.h \ QtxSplash.h \ QtxToolBar.h \ @@ -114,6 +115,7 @@ dist_libqtx_la_SOURCES= \ QtxPopupMgr.cxx \ QtxPreferenceMgr.cxx \ QtxResourceMgr.cxx \ + QtxRubberBand.cxx \ QtxSearchTool.cxx \ QtxSplash.cxx \ QtxToolBar.cxx \ diff --git a/src/Qtx/QtxRubberBand.cxx b/src/Qtx/QtxRubberBand.cxx new file mode 100755 index 000000000..1fb2fad37 --- /dev/null +++ b/src/Qtx/QtxRubberBand.cxx @@ -0,0 +1,313 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File: QtxRubberBand.cxx +// Author: Alexander A. BORODIN +// + +#include "QtxRubberBand.h" + +#include +#include +#include +#include +#include +#include +#include + +/*! + \class QtxAbstractRubberBand + \brief Analog of class QRubberBand with possibility of creation non-rectangular contour for selection. + + Currently this class does not support Style functionality in full. +*/ + +/*! + \brief Constructor + \param theParent parent widget + */ + +QtxAbstractRubberBand::QtxAbstractRubberBand( QWidget* theParent) + : QWidget( theParent/*,Qt::ToolTip*/ ), + myPoints(), + myIsClosed( false ) +{ + setAttribute(Qt::WA_TransparentForMouseEvents); +#ifndef WIN32 + setAttribute(Qt::WA_NoSystemBackground); +#endif //WIN32 + setAttribute(Qt::WA_WState_ExplicitShowHide); + setVisible(false); + theParent->installEventFilter(this); + setGeometry( QRect(QPoint(0,0), theParent->size() ) ); +} + +/*! + \brief Destructor + */ +QtxAbstractRubberBand::~QtxAbstractRubberBand() +{ +} + +void QtxAbstractRubberBand::clearGeometry() +{ + myPoints.clear(); +} + +bool QtxAbstractRubberBand::isClosed() +{ + return myIsClosed; +} + +void QtxAbstractRubberBand::paintEvent( QPaintEvent* theEvent ) +{ + if ( !myPoints.empty() ) + { + QPixmap tiledPixmap(16, 16); + + QPainter pixmapPainter(&tiledPixmap); + pixmapPainter.setPen(Qt::NoPen); + pixmapPainter.setBrush(QBrush( Qt::black, Qt::Dense4Pattern )); + pixmapPainter.setBackground(QBrush( Qt::white )); + pixmapPainter.setBackgroundMode(Qt::OpaqueMode); + pixmapPainter.drawRect(0, 0, tiledPixmap.width(), tiledPixmap.height()); + pixmapPainter.end(); + // ### workaround for borked XRENDER + tiledPixmap = QPixmap::fromImage(tiledPixmap.toImage()); + + + + QPainter aPainter( this ); + aPainter.setRenderHint( QPainter::Antialiasing ); + QRect r = myPoints.boundingRect(); + aPainter.setClipRegion( r.normalized().adjusted( -1, -1, 2, 2 ) ); + aPainter.drawTiledPixmap( 0, 0, width(), height(), tiledPixmap); + + aPainter.end(); + + /* + + + +#ifdef WIN32 + QPixmap anImage( size() ); +#else + QImage anImage( size(), QImage::Format_ARGB32_Premultiplied ); +#endif + + anImage.fill( Qt::transparent ); + QPainter aImgPainter( &anImage ); + aImgPainter.setRenderHint( QPainter::Antialiasing ); + aImgPainter.setCompositionMode(QPainter::CompositionMode_Source); + + QPen aPen( Qt::black ); + aPen.setWidth( 2 ); + aImgPainter.setPen( aPen ); + + aImgPainter.drawPolyline( myPoints ); + if ( myIsClosed && myPoints.last() != myPoints.first() ) + aImgPainter.drawLine( myPoints.last(), myPoints.first() ); + + //aImgPainter.setPen(Qt::NoPen); + //aImgPainter.setBrush(QBrush( Qt::white, Qt::Dense4Pattern)); + //aImgPainter.setCompositionMode(QPainter::CompositionMode_SourceAtop); + //aImgPainter.drawRect(0, 0, width(), height()); + aImgPainter.end(); + + QPainter aPainter( this ); + aPainter.drawPolyline( myPoints ); + if ( myIsClosed && myPoints.last() != myPoints.first() ) + aPainter.drawLine( myPoints.last(), myPoints.first() ); + +#ifdef WIN32 + aPainter.drawPixmap( 0, 0, anImage ); +#else + aPainter.drawImage( 0, 0, anImage ); + #endif + aPainter.end();*/ + + } +} + +void QtxAbstractRubberBand::showEvent( QShowEvent* theEvent ) +{ + raise(); + theEvent->ignore(); +} + +void QtxAbstractRubberBand::moveEvent( QMoveEvent* ) +{ +} + +void QtxAbstractRubberBand::resizeEvent( QResizeEvent* ) +{ +} + +bool QtxAbstractRubberBand::eventFilter( QObject* obj, QEvent* e ) +{ + if ( obj && obj == parent() && e->type() == QEvent::Resize ) + { + QWidget* p = (QWidget*)parent(); + setGeometry( QRect(QPoint(0,0), p->size() ) ); + } + return QWidget::eventFilter( obj, e ); +} + +QRegion createRegion( const QPointF& p1, const QPointF& p2 ) +{ + if ( p1 == p2 ) + return QRegion(); + + QLineF n = QLineF( p1, p2 ).normalVector();//.unitVector(); + n.setLength( 1 ); + n.translate( p1 * -1 ); + QPointF nPoint = n.p2(); + + QPolygonF p; + p << p1 + nPoint << p2 + nPoint << p2 - nPoint << p1 - nPoint << p1 + nPoint; + + return QRegion( p.toPolygon() ); +} + +void QtxAbstractRubberBand::updateMask() +{ + QRegion r; + + QVectorIterator it(myPoints); + while( it.hasNext() ) + { + QPoint p = it.next(); + if( !it.hasNext() ) + break; + + QPoint np = it.peekNext(); + + if ( p == np ) continue; + + r += createRegion( p, np ); + } + + if ( isClosed() ) + r += createRegion( myPoints.last(), myPoints.first() ); + + setMask( r ); + +} + + +QtxRectRubberBand::QtxRectRubberBand(QWidget* parent) + :QtxAbstractRubberBand( parent ) +{ + myPoints.resize( 4 ); + myIsClosed = true; +} + +QtxRectRubberBand::~QtxRectRubberBand() +{ +} + +void QtxRectRubberBand::initGeometry( const QRect& theRect ) +{ + myPoints.clear(); + myPoints << theRect.topLeft() << theRect.topRight() << theRect.bottomRight() << theRect.bottomLeft(); + //setMask( QRegion( myPoints ) ); + updateMask(); +} + +void QtxRectRubberBand::setStartPoint( const QPoint& thePoint ) +{ + myPoints[0] = thePoint; + myPoints[1].setY( thePoint.y() ); + myPoints[3].setX( thePoint.x() ); + updateMask(); +} + +void QtxRectRubberBand::setEndPoint( const QPoint& thePoint) +{ + myPoints[2] = thePoint; + myPoints[1].setX( thePoint.x() ); + myPoints[3].setY( thePoint.y() ); + updateMask(); +} + +void QtxRectRubberBand::clearGeometry() +{ + QMutableVectorIterator i(myPoints); + while (i.hasNext()) + { + i.next(); + i.setValue( QPoint( -1, -1 ) ); + } +} + + +QtxPolyRubberBand::QtxPolyRubberBand(QWidget* parent) + :QtxAbstractRubberBand( parent ) +{ +} + +QtxPolyRubberBand::~QtxPolyRubberBand() +{ +} + +void QtxPolyRubberBand::initGeometry( const QPolygon& thePoints ) +{ + myPoints = thePoints; + updateMask(); +} + +void QtxPolyRubberBand::initGeometry( const QPoint& thePoint ) +{ + myPoints.clear(); + myPoints << thePoint; + updateMask(); +} + +void QtxPolyRubberBand::addNode( const QPoint& thePoint ) +{ + myPoints << thePoint; + updateMask(); +} + +void QtxPolyRubberBand::replaceLastNode( const QPoint& thePoint ) +{ + if ( !myPoints.empty() ) + { + myPoints.pop_back(); + myPoints << thePoint; + updateMask(); + } +} + +void QtxPolyRubberBand::removeLastNode() +{ + if ( !myPoints.empty() ) + { + myPoints.pop_back(); + updateMask(); + } +} + +void QtxPolyRubberBand::setClosed( bool theFlag ) +{ + if (myIsClosed != theFlag ) + { + myIsClosed = theFlag; + updateMask(); + } +} diff --git a/src/Qtx/QtxRubberBand.h b/src/Qtx/QtxRubberBand.h new file mode 100755 index 000000000..e16426167 --- /dev/null +++ b/src/Qtx/QtxRubberBand.h @@ -0,0 +1,89 @@ +// Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// 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 +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File: QtxRubberBand.h +// Author: Alexander A. BORODIN +// + +#ifndef QTXRUBBERBAND_H +#define QTXRUBBERBAND_H + +#include "Qtx.h" + +#include + +class QTX_EXPORT QtxAbstractRubberBand: public QWidget +{ +protected: + QtxAbstractRubberBand( QWidget* ); + +public: + virtual ~QtxAbstractRubberBand(); + + virtual void clearGeometry(); + + bool isClosed(); + +protected: + virtual void paintEvent( QPaintEvent* ); + virtual void showEvent( QShowEvent* ); + virtual void moveEvent( QMoveEvent* ); + virtual void resizeEvent( QResizeEvent* ); + + virtual bool eventFilter( QObject*, QEvent* ); + + virtual void updateMask(); + +protected: + QPolygon myPoints; + + bool myIsClosed; +}; + +class QTX_EXPORT QtxRectRubberBand: public QtxAbstractRubberBand +{ +public: + + QtxRectRubberBand( QWidget* ); + virtual ~QtxRectRubberBand(); + + void initGeometry( const QRect& ); + void setStartPoint( const QPoint& ); + void setEndPoint( const QPoint& ); + + virtual void clearGeometry(); +}; + +class QTX_EXPORT QtxPolyRubberBand: public QtxAbstractRubberBand +{ +public: + + QtxPolyRubberBand( QWidget* ); + virtual ~QtxPolyRubberBand(); + + void initGeometry( const QPolygon& ); + void initGeometry( const QPoint& ); + + void addNode( const QPoint& ); + void replaceLastNode( const QPoint& ); + void removeLastNode(); + + void setClosed( bool ); +}; + +#endif //QTXRUBBERBAND_H -- 2.39.2