]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
Bug NPAL16761 - EDF 550 GEOM : Polyline to select objects
authorouv <ouv@opencascade.com>
Thu, 8 Nov 2007 11:19:02 +0000 (11:19 +0000)
committerouv <ouv@opencascade.com>
Thu, 8 Nov 2007 11:19:02 +0000 (11:19 +0000)
src/OCCViewer/Makefile.am
src/OCCViewer/OCCViewer_ViewModel.cxx
src/OCCViewer/OCCViewer_ViewPort.cxx
src/OCCViewer/OCCViewer_ViewSketcher.cxx [new file with mode: 0755]
src/OCCViewer/OCCViewer_ViewSketcher.h [new file with mode: 0755]
src/OCCViewer/OCCViewer_ViewWindow.cxx
src/OCCViewer/OCCViewer_ViewWindow.h

index c244074a1f9da2f23c4f5d0492f62f4c2e4eb1c1..2bfc88875c944a25c531834f447e6d200a309e58 100755 (executable)
@@ -31,6 +31,7 @@ salomeinclude_HEADERS= \
        OCCViewer_ViewModel.h \
        OCCViewer_ViewPort3d.h \
        OCCViewer_ViewPort.h \
+       OCCViewer_ViewSketcher.h \
        OCCViewer_ViewWindow.h \
        OCCViewer_VService.h \
        OCCViewer_CreateRestoreViewDlg.h \
@@ -44,6 +45,7 @@ dist_libOCCViewer_la_SOURCES= \
        OCCViewer_ViewModel.cxx \
        OCCViewer_ViewPort3d.cxx \
        OCCViewer_ViewPort.cxx \
+       OCCViewer_ViewSketcher.cxx \
        OCCViewer_ViewWindow.cxx \
        OCCViewer_VService.cxx \
        OCCViewer_CreateRestoreViewDlg.cxx \
@@ -55,6 +57,7 @@ MOC_FILES= \
        OCCViewer_ViewModel_moc.cxx \
        OCCViewer_ViewPort3d_moc.cxx \
        OCCViewer_ViewPort_moc.cxx \
+       OCCViewer_ViewSketcher_moc.cxx \
        OCCViewer_ViewWindow_moc.cxx \
        OCCViewer_ViewManager_moc.cxx \
        OCCViewer_CreateRestoreViewDlg_moc.cxx \
index a58e95624754b30669963ff04f1d12bb8d3ecde4..5e64aafb371914ef13e06cded138e3adf315bb0e 100755 (executable)
@@ -129,6 +129,7 @@ void OCCViewer_Viewer::initView( OCCViewer_ViewWindow* view )
 {
   if ( view ) {
     view->initLayout();
+    view->initSketchers();
     
     OCCViewer_ViewPort3d* vp3d = view->getViewPort();
     if ( vp3d )
index ff4ef0551e36c7938977cd523b6cf2a944c16287..b0c6e617e92ee5ae0df3f86438e64ef90403adb6 100755 (executable)
@@ -196,7 +196,7 @@ void OCCViewer_ViewPort::initialize()
 {
   myPopupActions.setAutoDelete( true );
   myPaintersRedrawing = false;
-  myEnableSketching = false;
+  myEnableSketching = true;
   myEnableTransform = true;
   
   setMouseTracking( true );
diff --git a/src/OCCViewer/OCCViewer_ViewSketcher.cxx b/src/OCCViewer/OCCViewer_ViewSketcher.cxx
new file mode 100755 (executable)
index 0000000..a6e8d8e
--- /dev/null
@@ -0,0 +1,536 @@
+// 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
+//
+
+#include "OCCViewer_ViewSketcher.h"
+#include "OCCViewer_ViewWindow.h"
+#include "OCCViewer_ViewPort3d.h"
+
+#include <qapplication.h>
+#include <qpainter.h>
+#include <qpointarray.h>
+
+/****************************************************************
+**  Class: OCCViewer_ViewSketcher
+**  Level: Public
+*****************************************************************/
+
+OCCViewer_ViewSketcher::OCCViewer_ViewSketcher( OCCViewer_ViewWindow* vw, int type )
+: QObject( vw ),
+mySketchButton( Qt::LeftButton ),
+mypViewWindow( vw ),
+myType( type ),
+mypData( 0 ),
+myResult( Neutral ),
+myButtonState( 0 )
+{
+}
+
+OCCViewer_ViewSketcher::~OCCViewer_ViewSketcher()
+{
+}
+
+void OCCViewer_ViewSketcher::activate()
+{
+  OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
+
+  mySavedCursor = avp->cursor();
+  avp->setCursor( Qt::PointingHandCursor );
+  avp->installEventFilter( this );
+  qApp->installEventFilter( this );
+
+  connect( avp, SIGNAL( vpDrawExternal( QPainter* ) ), this, SLOT( onDrawViewPort() ) );
+
+  myStart = QPoint();
+  myResult = Neutral;
+
+  onActivate();
+}
+
+void OCCViewer_ViewSketcher::deactivate()
+{
+  OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
+
+  disconnect( avp, SIGNAL( vpDrawExternal( QPainter* ) ), this, SLOT( onDrawViewPort() ) );
+
+  qApp->removeEventFilter( this );
+  avp->removeEventFilter( this );
+  avp->setCursor( mySavedCursor );
+
+  onDeactivate();
+}
+
+int OCCViewer_ViewSketcher::type() const
+{
+  return myType;
+}
+
+void* OCCViewer_ViewSketcher::data() const
+{
+  return mypData;
+}
+
+int OCCViewer_ViewSketcher::result() const
+{
+  return myResult;
+}
+
+int OCCViewer_ViewSketcher::buttonState() const
+{
+  return myButtonState;
+}
+
+void OCCViewer_ViewSketcher::onActivate()
+{
+}
+
+void OCCViewer_ViewSketcher::onDeactivate()
+{
+}
+
+bool OCCViewer_ViewSketcher::isDefault() const
+{
+  return true;
+}
+
+bool OCCViewer_ViewSketcher::eventFilter( QObject* o, QEvent* e )
+{
+  OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
+
+  SketchState state = EnTrain;
+  bool ignore = false;
+  if ( o == avp )
+  {
+    switch ( e->type() )
+    {
+      case QEvent::MouseMove:
+      case QEvent::MouseButtonPress:
+      case QEvent::MouseButtonRelease:
+      case QEvent::MouseButtonDblClick:
+      {
+        QMouseEvent* me = (QMouseEvent*)e;
+
+        myButtonState = me->state();
+        if ( e->type() == QEvent::MouseButtonPress )
+          myButtonState |= me->button();
+
+        if ( myStart.isNull() && ( myButtonState & sketchButton() ) )
+        {
+          state = Debut;
+          myStart = me->pos();
+        }
+
+        myCurr = me->pos();
+
+        onMouse( me );
+
+        if ( myResult != Neutral )
+          state = Fin;
+
+        ignore = true;
+        break;
+      }
+      case QEvent::Hide:
+      case QEvent::HideToParent:
+        myResult = Reject;
+        onSketch( Fin );
+        break;
+      default:
+        break;
+    }
+  }
+  if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease )
+  {
+    ignore = onKey( (QKeyEvent*)e );
+    if ( myResult != Neutral )
+      state = Fin;
+  }
+
+  if ( ignore )
+  {
+    onSketch( state );
+    return true;
+  }
+  return QObject::eventFilter( o, e );
+}
+
+void OCCViewer_ViewSketcher::onDrawViewPort()
+{
+  onSketch( Debut );
+}
+
+bool OCCViewer_ViewSketcher::onKey( QKeyEvent* )
+{
+  return false;
+}
+
+void OCCViewer_ViewSketcher::onMouse( QMouseEvent* )
+{
+}
+
+int OCCViewer_ViewSketcher::sketchButton()
+{
+  return mySketchButton;
+}
+
+void OCCViewer_ViewSketcher::setSketchButton( int b )
+{
+  mySketchButton = b;
+}
+
+/****************************************************************
+**  Class: OCCViewer_RectSketcher
+**  Level: Public
+*****************************************************************/
+
+OCCViewer_RectSketcher::OCCViewer_RectSketcher( OCCViewer_ViewWindow* vw, int typ )
+: OCCViewer_ViewSketcher( vw, typ )
+{
+}
+
+OCCViewer_RectSketcher::~OCCViewer_RectSketcher()
+{
+  delete mypData;
+}
+
+void OCCViewer_RectSketcher::onActivate()
+{
+  mypData = new QRect();
+}
+
+void OCCViewer_RectSketcher::onDeactivate()
+{
+  delete mypData;
+  mypData = 0;
+}
+
+bool OCCViewer_RectSketcher::onKey( QKeyEvent* e )
+{
+  if ( e->key() == Qt::Key_Escape )
+    myResult = Reject;
+  else if ( e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return )
+    myResult = Accept;
+
+  return true;
+}
+
+void OCCViewer_RectSketcher::onMouse( QMouseEvent* e )
+{
+  OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
+
+  if ( avp->rect().contains( myCurr ) )
+    avp->setCursor( Qt::PointingHandCursor );
+  else
+    avp->setCursor( Qt::ForbiddenCursor );
+
+  if ( e->type() == QEvent::MouseButtonRelease && e->button() == sketchButton() )
+  {
+    myResult = Accept;
+    QApplication::postEvent( avp, new QMouseEvent( e->type(), e->pos(),
+                                                   e->globalPos(), e->state(), e->button() ) );
+  }
+}
+
+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.setRasterOp( Qt::XorROP );
+    if ( state != Debut && !sketchRect->isEmpty() )
+      p.drawRect( *sketchRect );
+    *sketchRect = rect;
+    if ( !rect.isEmpty() && state != Fin )
+      p.drawRect( *sketchRect );
+  }
+
+  if ( state == Fin )
+  {
+    QApplication::syncX();  /* force rectangle redrawing */
+    mypViewWindow->activateSketching( OCCViewer_ViewWindow::NoSketching );
+  }
+}
+
+/****************************************************************
+**  Class: OCCViewer_PolygonSketcher
+**  Level: Public
+*****************************************************************/
+
+OCCViewer_PolygonSketcher::OCCViewer_PolygonSketcher( OCCViewer_ViewWindow* vw, int typ )
+: OCCViewer_ViewSketcher( vw, typ ),
+  myDbl           ( false ),
+  myToler         ( 5, 5 ),
+  mypPoints        ( 0L ),
+  myAddButton     ( 0 ),
+  myDelButton     ( 0 )
+{
+  mySketchButton = Qt::RightButton;
+}
+
+OCCViewer_PolygonSketcher::~OCCViewer_PolygonSketcher()
+{
+  delete mypPoints;
+  delete mypData;
+}
+
+void OCCViewer_PolygonSketcher::onActivate()
+{
+  myDbl = false;
+  mypData = new QPointArray( 0 );
+  mypPoints = new QPointArray( 0 );
+
+  switch ( sketchButton() )
+  {
+  case Qt::LeftButton:
+    myAddButton = Qt::RightButton;
+    myDelButton = Qt::MidButton;
+    break;
+  case Qt::MidButton:
+    myAddButton = Qt::LeftButton;
+    myDelButton = Qt::RightButton;
+    break;
+  case Qt::RightButton:
+  default:
+    myAddButton = Qt::LeftButton;
+    myDelButton = Qt::MidButton;
+    break;
+  };
+}
+
+void OCCViewer_PolygonSketcher::onDeactivate()
+{
+  delete mypPoints;
+  mypPoints = 0;
+  delete mypData;
+  mypData = 0;
+}
+
+bool OCCViewer_PolygonSketcher::onKey( QKeyEvent* e )
+{
+  if ( e->key() == Qt::Key_Escape )
+  {
+    myResult = Reject;
+    return true;
+  }
+  else if ( e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return )
+  {
+    QPointArray* points = (QPointArray*)data();
+    if ( points->count() )
+    {
+      QPoint last = points->point( points->count() - 1 );
+      if ( last != myCurr )
+      {
+        points->resize( points->count() + 1 );
+        points->setPoint( points->count() - 1, myCurr );
+      }
+    }
+    myResult = Accept;
+    return true;
+  }
+  else if ( e->key() == Qt::Key_Backspace && e->type() == QEvent::KeyRelease )
+  {
+    QPointArray* points = (QPointArray*)data();
+    if ( points->count() > 1 )
+      points->resize( points->count() - 1 );
+    onMouse( 0 );
+    return true;
+  }
+
+  return true;
+}
+
+void OCCViewer_PolygonSketcher::onMouse( QMouseEvent* e )
+{
+  OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
+
+  QPointArray* points = (QPointArray*)data();
+  if ( !points->count() && !myStart.isNull() )
+  {
+    points->resize( points->count() + 1 );
+    points->setPoint( points->count() - 1, myStart );
+  }
+
+  bool closed = false;
+  bool valid = avp->rect().contains( myCurr );
+  if ( !myStart.isNull() )
+  {
+    QRect aRect( myStart.x() - myToler.width(), myStart.y() - myToler.height(),
+                 2 * myToler.width(), 2 * myToler.height() );
+    closed = aRect.contains( myCurr );
+  }
+  valid = valid && isValid( points, myCurr );
+  if ( closed && !valid )
+    closed = false;
+
+  if ( closed )
+    avp->setCursor( Qt::CrossCursor );
+  else if ( valid )
+    avp->setCursor( Qt::PointingHandCursor );
+  else
+    avp->setCursor( Qt::ForbiddenCursor );
+
+  if ( !e )
+    return;
+
+  if ( e->type() == QEvent::MouseButtonRelease && ( e->button() & sketchButton() ) )
+  {
+    myResult = Reject;
+    QApplication::postEvent( avp, new QMouseEvent( e->type(), e->pos(),
+                                                   e->globalPos(), e->state(), e->button() ) );
+  }
+  else if ( e->type() == QEvent::MouseButtonRelease && ( e->button() & myAddButton ) )
+  {
+    if ( closed )
+      myResult = Accept;
+    else
+    {
+      if ( myStart.isNull() )
+        myStart = myCurr;
+      else
+      {
+        QPoint last = points->point( points->count() - 1 );
+        if ( last != myCurr && valid )
+        {
+          points->resize( points->count() + 1 );
+          points->setPoint( points->count() - 1, myCurr );
+        }
+        if ( valid && myDbl )
+          myResult = Accept;
+      }
+    }
+  }
+  else if ( ( e->type() == QEvent::MouseButtonRelease && ( e->button() & myDelButton ) ) ||
+            ( e->type() == QEvent::MouseButtonDblClick && ( e->button() & myDelButton ) ) )
+  {
+    if ( points->count() > 1 )
+      points->resize( points->count() - 1 );
+    onMouse( 0 );
+  }
+  myDbl = e->type() == QEvent::MouseButtonDblClick && ( e->button() & myAddButton );
+}
+
+void OCCViewer_PolygonSketcher::onSketch( SketchState state )
+{
+  OCCViewer_ViewPort3d* avp = mypViewWindow->getViewPort();
+
+  QPointArray* points = (QPointArray*)data();
+  QPainter p( avp );
+  p.setPen( Qt::white );
+  p.setRasterOp( Qt::XorROP );
+  if ( state != Debut )
+    p.drawPolyline( *mypPoints );
+
+  if ( points->count() )
+  {
+    mypPoints->resize( points->count() + 1 );
+    for ( uint i = 0; i < points->count(); i++ )
+      mypPoints->setPoint( i, points->point( i ) );
+    mypPoints->setPoint( points->count(), myCurr );
+    if ( state != Fin )
+      p.drawPolyline( *mypPoints );
+  }
+
+  if ( state == Fin )
+  {
+    QApplication::syncX();
+    mypViewWindow->activateSketching( OCCViewer_ViewWindow::NoSketching );
+  }
+}
+
+bool OCCViewer_PolygonSketcher::isValid( const QPointArray* aPoints, const QPoint& aCur ) const
+{
+  if ( !aPoints->count() )
+    return true;
+
+  if ( aPoints->count() == 1 && aPoints->point( 0 ) == aCur )
+    return false;
+
+  const QPoint& aLast = aPoints->point( aPoints->count() - 1 );
+
+  if ( aLast == aCur )
+    return true;
+
+  bool res = true;
+  for ( uint i = 0; i < aPoints->count() - 1 && res; i++ )
+  {
+    const QPoint& aStart = aPoints->point( i );
+    const QPoint& anEnd  = aPoints->point( i + 1 );
+    res = !isIntersect( aStart, anEnd, aCur, aLast );
+  }
+
+  return res;
+}
+
+bool OCCViewer_PolygonSketcher::isIntersect( const QPoint& aStart1, const QPoint& anEnd1,
+                                            const QPoint& aStart2, const QPoint& anEnd2 ) const
+{
+  if ( ( aStart1 == aStart2 && anEnd1 == anEnd2 ) ||
+       ( aStart1 == anEnd2 && anEnd1 == aStart2 ) )
+    return true;
+
+  if ( aStart1 == aStart2 || aStart2 == anEnd1 ||
+       aStart1 == anEnd2 || anEnd1 == anEnd2 )
+    return false;
+
+  double x11 = aStart1.x() * 1.0;
+  double x12 = anEnd1.x() * 1.0;
+  double y11 = aStart1.y() * 1.0;
+  double y12 = anEnd1.y() * 1.0;
+
+  double x21 = aStart2.x() * 1.0;
+  double x22 = anEnd2.x() * 1.0;
+  double y21 = aStart2.y() * 1.0;
+  double y22 = anEnd2.y() * 1.0;
+
+  double k1 = x12 == x11 ? 0 : ( y12 - y11 ) / ( x12 - x11 );
+  double k2 = x22 == x21 ? 0 : ( y22 - y21 ) / ( x22 - x21 );
+
+  double b1 = y11 - k1 * x11;
+  double b2 = y21 - k2 * x21;
+
+  if ( k1 == k2 )
+  {
+    if ( b1 != b2 )
+      return false;
+    else
+      return !( ( QMAX( x11, x12 ) <= QMIN( x21, x22 ) ||
+                  QMIN( x11, x12 ) >= QMAX( x21, x22 ) ) &&
+                ( QMAX( y11, y12 ) <= QMIN( y21, y22 ) ||
+                  QMIN( y11, y12 ) >= QMAX( y21, y22 ) ) );
+  }
+  else
+  {
+    double x0 = ( b2 - b1 ) / ( k1 - k2 );
+    double y0 = ( k1 * b2 - k2 * b1 ) / ( k1 - k2 );
+
+    if ( QMIN( x11, x12 ) < x0 && x0 < QMAX( x11, x12 ) &&
+         QMIN( y11, y12 ) < y0 && y0 < QMAX( y11, y12 ) &&
+         QMIN( x21, x22 ) < x0 && x0 < QMAX( x21, x22 ) &&
+         QMIN( y21, y22 ) < y0 && y0 < QMAX( y21, y22 ) )
+      return true;
+  }
+  return false;
+}
+
+
diff --git a/src/OCCViewer/OCCViewer_ViewSketcher.h b/src/OCCViewer/OCCViewer_ViewSketcher.h
new file mode 100755 (executable)
index 0000000..367ece1
--- /dev/null
@@ -0,0 +1,137 @@
+// 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
+//
+#ifndef OCCVIEWER_VIEWSKETCHER_H
+#define OCCVIEWER_VIEWSKETCHER_H
+
+#include "OCCViewer.h"
+
+#include <qobject.h>
+#include <qcursor.h>
+
+class OCCViewer_ViewWindow;
+
+#ifdef WNT
+#pragma warning ( disable:4251 )
+#endif
+
+/*!
+  \class OCCViewer_ViewSketcher
+*/
+
+class OCCVIEWER_EXPORT OCCViewer_ViewSketcher : public QObject
+{
+  Q_OBJECT
+
+public:
+  enum { Neutral, Accept, Reject };
+
+public:
+  OCCViewer_ViewSketcher( OCCViewer_ViewWindow*, int );
+  virtual ~OCCViewer_ViewSketcher();
+
+public:
+  int                          type() const;
+  int                          result() const;
+  int                          buttonState() const;
+  void*                        data() const;
+
+  void                         activate();
+  void                         deactivate();
+
+  int                          sketchButton();
+  void                         setSketchButton( int );
+
+  virtual bool                 isDefault() const;
+  virtual bool                 eventFilter( QObject*, QEvent* );
+
+private slots:
+  void                         onDrawViewPort();
+
+protected:
+  enum SketchState { Debut, EnTrain, Fin };
+  virtual bool                 onKey( QKeyEvent* );
+  virtual void                 onMouse( QMouseEvent* );
+  virtual void                 onSketch( SketchState ) = 0;
+  virtual void                 onActivate();
+  virtual void                 onDeactivate();
+
+protected:
+  int                          mySketchButton;
+  OCCViewer_ViewWindow*        mypViewWindow;
+  int                          myType;
+  void*                        mypData;
+  int                          myResult;
+  QCursor                      mySavedCursor;
+  QPoint                       myStart, myCurr;
+  int                          myButtonState;
+};
+
+/*!
+  \class OCCViewer_RectSketcher
+*/
+
+class OCCVIEWER_EXPORT OCCViewer_RectSketcher : public OCCViewer_ViewSketcher
+{
+public:
+  OCCViewer_RectSketcher( OCCViewer_ViewWindow*, int );
+  virtual ~OCCViewer_RectSketcher();
+
+protected:
+  virtual bool                 onKey( QKeyEvent* );
+  virtual void                 onMouse( QMouseEvent* );
+  virtual void                 onSketch( SketchState );
+  virtual void                 onActivate();
+  virtual void                 onDeactivate();
+};
+
+/*!
+  \class OCCViewer_PolygonSketcher
+*/
+
+class OCCVIEWER_EXPORT OCCViewer_PolygonSketcher : public OCCViewer_ViewSketcher
+{
+public:
+  OCCViewer_PolygonSketcher( OCCViewer_ViewWindow*, int );
+  virtual ~OCCViewer_PolygonSketcher();
+
+protected:
+  virtual bool                 onKey( QKeyEvent* );
+  virtual void                 onMouse( QMouseEvent* );
+  virtual void                 onSketch( SketchState );
+  virtual void                 onActivate();
+  virtual void                 onDeactivate();
+
+private:
+  bool                         isValid( const QPointArray*, const QPoint& ) const;
+  bool                         isIntersect( const QPoint&, const QPoint&,
+                                            const QPoint&, const QPoint& ) const;
+
+private:
+  bool                         myDbl;
+  QSize                        myToler;
+  QPointArray*                 mypPoints;
+  int                          myAddButton;
+  int                          myDelButton;
+};
+
+#ifdef WNT
+#pragma warning( default:4251 )
+#endif
+
+#endif
index 0ec1a641d213a41b57c65d1b53e070bf467d3d61..78bd7147e870c31cda7a521668d7c1fd5b761668 100755 (executable)
@@ -22,6 +22,8 @@
 #include "OCCViewer_ViewWindow.h"
 #include "OCCViewer_ViewModel.h"
 #include "OCCViewer_ViewPort3d.h"
+#include "OCCViewer_ViewManager.h"
+#include "OCCViewer_ViewSketcher.h"
 #include "OCCViewer_CreateRestoreViewDlg.h"
 #include "OCCViewer_ClippingDlg.h"
 #include "OCCViewer_SetRotationPointDlg.h"
@@ -46,6 +48,7 @@
 #include <V3d_Plane.hxx>
 #include <gp_Dir.hxx>
 #include <gp_Pln.hxx>
+#include <TColgp_Array1OfPnt2d.hxx>
 
 #include <AIS_ListIteratorOfListOfInteractive.hxx>
 #include <AIS_Shape.hxx>
@@ -59,6 +62,7 @@
 #include <Graphic3d_MapOfStructure.hxx>
 #include <Graphic3d_Structure.hxx>
 
+static QEvent* l_mbPressEvent = 0;
 
 const char* imageZoomCursor[] = { 
 "32 32 3 1",
@@ -189,6 +193,9 @@ OCCViewer_ViewWindow::OCCViewer_ViewWindow(SUIT_Desktop* theDesktop, OCCViewer_V
   updateEnabledDrawMode();
   myClippingDlg = 0;
   mySetRotationPointDlg = 0;
+
+  mypSketcher = 0;
+  myCurSketch = -1;
 }
 
 /*!
@@ -387,6 +394,11 @@ void OCCViewer_ViewWindow::vpMousePressEvent(QMouseEvent* theEvent)
   }
   if ( transformRequested() ) 
     setTransformInProcess( true );              
+
+  /* we may need it for sketching... */
+  if ( l_mbPressEvent )
+    delete l_mbPressEvent;
+  l_mbPressEvent = new QMouseEvent( *theEvent );
 }
 
 
@@ -681,9 +693,8 @@ void OCCViewer_ViewWindow::vpMouseMoveEvent(QMouseEvent* theEvent)
     else
     {
       int aState = theEvent->state();
-      //int aButton = theEvent->button();
       if ( aState == Qt::LeftButton ||
-          aState == ( Qt::LeftButton | Qt::ShiftButton) )      {
+          aState == ( Qt::LeftButton | Qt::ShiftButton) ) {
        myDrawRect = myEnableDrawMode;
        if ( myDrawRect ) {
          drawRect();
@@ -695,6 +706,32 @@ void OCCViewer_ViewWindow::vpMouseMoveEvent(QMouseEvent* theEvent)
          }
        }
       } 
+      else if ( aState == Qt::RightButton || 
+               aState == ( Qt::RightButton | Qt::ShiftButton ) ) {
+       OCCViewer_ViewSketcher* sketcher = 0;
+       for ( OCCViewer_ViewSketcher* sk = mySketchers.first();
+             sk && !sketcher; sk = mySketchers.next() )
+       {
+         if( sk->isDefault() && sk->sketchButton() & ( aState & Qt::MouseButtonMask ) )
+           sketcher = sk;
+       }
+       if ( sketcher && myCurSketch == -1 )
+       {
+         activateSketching( sketcher->type() );
+         if ( mypSketcher )
+         {
+           myCurSketch = mypSketcher->sketchButton();
+
+           if ( l_mbPressEvent )
+           {
+             QApplication::sendEvent( getViewPort(), l_mbPressEvent );
+             delete l_mbPressEvent;
+             l_mbPressEvent = 0;
+           }
+           QApplication::sendEvent( getViewPort(), theEvent );
+         }
+       }
+      }
       else {
        emit mouseMoving( this, theEvent ); 
       }        
@@ -710,13 +747,24 @@ void OCCViewer_ViewWindow::vpMouseReleaseEvent(QMouseEvent* theEvent)
   switch ( myOperation ) {
   case NOTHING:
     {
+      int prevState = myCurSketch;
+      if(theEvent->state() == RightButton)
+      {
+       for ( OCCViewer_ViewSketcher* sk = mySketchers.first();
+             sk && myCurSketch != -1; sk = mySketchers.next() )
+       {
+         if( ( sk->sketchButton() & theEvent->state() ) && sk->sketchButton() == myCurSketch )
+           myCurSketch = -1;
+       }
+      }
+
       emit mouseReleased(this, theEvent);
-      if(theEvent->button() == RightButton)
+      if(theEvent->button() == RightButton && prevState == -1)
       {
-        QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
-                                  theEvent->pos(), theEvent->globalPos(),
-                                  theEvent->state() );
-        emit contextMenuRequested( &aEvent );
+       QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
+                                 theEvent->pos(), theEvent->globalPos(),
+                                 theEvent->state() );
+       emit contextMenuRequested( &aEvent );
       }
     }
     break;
@@ -758,6 +806,12 @@ void OCCViewer_ViewWindow::vpMouseReleaseEvent(QMouseEvent* theEvent)
     resetState(); 
     myViewPort->update();
   }
+
+  if ( l_mbPressEvent )
+  {
+    delete l_mbPressEvent;
+    l_mbPressEvent = 0;
+  }
 }
 
 /*!
@@ -1374,3 +1428,138 @@ void OCCViewer_ViewWindow::hideEvent( QHideEvent * theEvent )
   emit Hide( theEvent );
 }
 
+
+/*!
+    Creates default sketcher. [ virtual protected ]
+*/
+OCCViewer_ViewSketcher* OCCViewer_ViewWindow::createSketcher( int type )
+{
+  if ( type == Rect )
+    return new OCCViewer_RectSketcher( this, type );
+  if ( type == Polygon )
+    return new OCCViewer_PolygonSketcher( this, type );
+  return 0;
+}
+
+void OCCViewer_ViewWindow::initSketchers()
+{
+  if ( mySketchers.isEmpty() )
+  {
+    mySketchers.append( createSketcher( Rect ) );
+    mySketchers.append( createSketcher( Polygon ) );
+  }
+}
+
+OCCViewer_ViewSketcher* OCCViewer_ViewWindow::getSketcher( const int typ )
+{
+  OCCViewer_ViewSketcher* sketcher = 0;
+  for ( OCCViewer_ViewSketcher* sk = mySketchers.first();
+        sk && !sketcher; sk = mySketchers.next() )
+  {
+    if ( sk->type() == typ )
+      sketcher = sk;
+  }
+  return sketcher;
+}
+
+/*!
+    Handles requests for sketching in the active view. [ virtual public ]
+*/
+void OCCViewer_ViewWindow::activateSketching( int type )
+{
+  OCCViewer_ViewPort3d* vp = getViewPort();
+  if ( !vp )
+    return;
+
+  if ( !vp->isSketchingEnabled() )
+    return;
+
+  /* Finish current sketching */
+  if ( type == NoSketching )
+  {
+    if ( mypSketcher )
+    {
+      onSketchingFinished();
+      mypSketcher->deactivate();
+      mypSketcher = 0;
+    }
+  }
+  /* Activate new sketching */
+  else
+  {
+    activateSketching( NoSketching );  /* concurrency not suported */
+    mypSketcher = getSketcher( type );
+    if ( mypSketcher )
+    {
+      mypSketcher->activate();
+      onSketchingStarted();
+    }
+  }
+}
+
+/*!
+    Unhilights detected entities. [ virtual protected ]
+*/
+void OCCViewer_ViewWindow::onSketchingStarted()
+{
+}
+
+/*!
+    Selection by rectangle or polygon. [ virtual protected ]
+*/
+void OCCViewer_ViewWindow::onSketchingFinished()
+{
+  if ( mypSketcher && mypSketcher->result() == OCCViewer_ViewSketcher::Accept )
+  {
+    Handle(AIS_InteractiveContext) ic = myModel->getAISContext();
+    bool append = bool( mypSketcher->buttonState() & Qt::ShiftButton );
+    switch( mypSketcher->type() )
+    {
+    case Rect:
+      {
+       QRect* aRect = (QRect*)mypSketcher->data();
+       if( aRect )
+       {
+         int aLeft = aRect->left();
+         int aRight = aRect->right();
+         int aTop = aRect->top();
+         int aBottom = aRect->bottom();
+
+         if( append )
+           ic->ShiftSelect( aLeft, aBottom, aRight, aTop, getViewPort()->getView(), Standard_False );
+         else
+           ic->Select( aLeft, aBottom, aRight, aTop, getViewPort()->getView(), Standard_False );
+       }
+      }
+      break;
+    case Polygon:
+      {
+        QPointArray* aPolygon = (QPointArray*)mypSketcher->data();
+        if( aPolygon )
+        {
+         int size = aPolygon->size();
+         TColgp_Array1OfPnt2d anArray( 1, size );
+
+         QPointArray::Iterator it = aPolygon->begin();
+         QPointArray::Iterator itEnd = aPolygon->end();
+         for( int index = 1; it != itEnd; ++it, index++ )
+         {
+           QPoint aPoint = *it;
+           anArray.SetValue( index, gp_Pnt2d( aPoint.x(), aPoint.y() ) );
+         }
+
+         if( append )
+           ic->ShiftSelect( anArray, getViewPort()->getView(), Standard_False );
+         else
+           ic->Select( anArray, getViewPort()->getView(), Standard_False );
+        }
+      }
+      break;
+    default:
+      break;
+    }
+
+    OCCViewer_ViewManager* aViewMgr = ( OCCViewer_ViewManager* )getViewManager();
+    aViewMgr->getOCCViewer()->performSelectionChanged();
+  }
+}
index 9c384141227903d7d5837155ef5718bda16959af..698a9f095f96a623e40a8e74c3f06e42bd1ea481 100755 (executable)
@@ -30,6 +30,7 @@
 
 class SUIT_Desktop;
 class OCCViewer_ViewPort3d;
+class OCCViewer_ViewSketcher;
 
 class OCCViewer_ClippingDlg;
 class OCCViewer_SetRotationPointDlg;
@@ -49,6 +50,8 @@ public:
 
   enum RotationPointType{ GRAVITY, SELECTED };
 
+  enum SketchingType { NoSketching, Rect, Polygon };
+
   OCCViewer_ViewWindow(SUIT_Desktop* theDesktop, OCCViewer_Viewer* theModel);
        virtual ~OCCViewer_ViewWindow() {};
 
@@ -71,6 +74,11 @@ public:
 
   virtual QString   getVisualParameters();
   virtual void      setVisualParameters( const QString& parameters );
+
+  virtual void            initSketchers();
+  OCCViewer_ViewSketcher* getSketcher( const int );
+
+  void                    activateSketching( int );
  
 public slots:
   void onFrontView();
@@ -145,6 +153,16 @@ protected:
 
   bool computeGravityCenter( double& theX, double& theY, double& theZ );
 
+  virtual void                          onSketchingStarted();
+  virtual void                          onSketchingFinished();
+
+  virtual OCCViewer_ViewSketcher*       createSketcher( int );
+
+  OCCViewer_ViewSketcher*               mypSketcher;
+  QList<OCCViewer_ViewSketcher>         mySketchers;
+
+  int                                   myCurSketch;
+
   OperationType         myOperation;
   OCCViewer_Viewer*     myModel;
   OCCViewer_ViewPort3d* myViewPort;