/*************************************************************************** * Copyright (c) 2005 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * 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 Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include # include # include # include # include # include # include # include # include # include #endif #include #include "MouseSelection.h" #include "View3DInventor.h" #include "View3DInventorViewer.h" using namespace Gui; AbstractMouseSelection::AbstractMouseSelection() : _pcView3D(0) { m_bInner = true; mustRedraw = false; } void AbstractMouseSelection::grabMouseModel( Gui::View3DInventorViewer* viewer ) { _pcView3D=viewer; m_cPrevCursor = _pcView3D->getWidget()->cursor(); // do initialization of your mousemodel initialize(); } void AbstractMouseSelection::releaseMouseModel() { // do termination of your mousemodel terminate(); _pcView3D->getWidget()->setCursor(m_cPrevCursor); _pcView3D = 0; } void AbstractMouseSelection::redraw() { // Note: For any reason it does not work to do a redraw in the actualRedraw() method of the // viewer class. So, we do the redraw when the user continues moving the cursor. E.g. have // a look to PolyPickerSelection::draw() mustRedraw = true; } int AbstractMouseSelection::handleEvent(const SoEvent * const ev, const SbViewportRegion& vp) { int ret=Continue; const SbVec2s& sz = vp.getWindowSize(); short w,h; sz.getValue(w,h); SbVec2s loc = ev->getPosition(); short x,y; loc.getValue(x,y); y = h-y; // the origin is at the left bottom corner (instead of left top corner) if (ev->getTypeId().isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) { const SoMouseButtonEvent * const event = (const SoMouseButtonEvent *) ev; const SbBool press = event->getState() == SoButtonEvent::DOWN ? TRUE : FALSE; if (press) { _clPoly.push_back(ev->getPosition()); ret = mouseButtonEvent(static_cast(ev), QPoint(x,y)); } else { ret = mouseButtonEvent(static_cast(ev), QPoint(x,y)); } } else if (ev->getTypeId().isDerivedFrom(SoLocation2Event::getClassTypeId())) { ret = locationEvent(static_cast(ev), QPoint(x,y)); } else if (ev->getTypeId().isDerivedFrom(SoKeyboardEvent::getClassTypeId())) { ret = keyboardEvent(static_cast(ev)); } if (ret == Restart) _clPoly.clear(); return ret; } // ----------------------------------------------------------------------------------- BaseMouseSelection::BaseMouseSelection() : AbstractMouseSelection() { } // ----------------------------------------------------------------------------------- #if 0 /* XPM */ static const char *cursor_polypick[]={ "32 32 2 1", "# c #646464", ". c None", "................................", "................................", ".......#........................", ".......#........................", ".......#........................", "................................", ".......#........................", "..###.###.###...................", ".......#...............#........", "......................##........", ".......#..............#.#.......", ".......#.............#..#.......", ".......#............#...#.......", "....................#....#......", "...................#.....#......", "..................#......#......", "............#.....#.......#.....", "...........#.##..#........#.....", "..........#....##.........#.....", ".........#...............#......", "........#................#......", ".......#................#.......", "......#.................#.......", ".....#.................#........", "....#####..............#........", ".........#########....#.........", "..................#####.........", "................................", "................................", "................................", "................................", "................................"}; /* XPM */ static const char *cursor_scissors[]={ "32 32 3 1", "# c #000000", "+ c #ffffff", ". c None", "....+...........................", "....+...........................", "....+...........................", "................................", "+++.+.+++.......................", "................................", "....+...........................", "....+...................#####...", "....+.................########..", ".....................#########..", ".....###............##########..", "....##++##.........#####...###..", "...#++++++##.......####...####..", "...##+++++++#......####.######..", ".....#+++++++##....##########...", "......##+++++++##.##########....", "........##+++++++#########......", "..........#+++++++#####.........", "...........##+++++####..........", "...........##+++++###...........", ".........##+++++++########......", "........##+++++++###########....", "......##+++++++##.###########...", "....##+++++++##....##########...", "...#+++++++##......####..#####..", "...#++++++#........#####..####..", "....##++##..........#####..###..", "......#.............##########..", ".....................#########..", ".......................######...", "................................", "................................"}; #endif static const char *cursor_cut_scissors[]={ "32 32 6 1", "a c #800000", "c c #808080", "+ c #c0c0c0", "b c #ff0000", "# c #ffffff", ". c None", "....#...........................", "....#...........................", "....#...........................", "................................", "###.#.###.......................", "................................", "....#...........................", "....#...................aaaaa...", "....#.................aabbbbba..", ".....................abbbbbbba..", ".....ccc............abbaaaaabb..", "....cc++cc.........babaa...aba..", "...c+#++++cc.......abba...abba..", "...cc+#+++++c......abba.aabbaa..", ".....c+++++#+cc....abbaaabbaa...", "......cc+#+++#+cc.aabbbbbbaa....", "........cc+#+++#+cabbbaaaa......", "..........c+++++++abbaa.........", "...........cc+++#+aaaa..........", "...........cc+#+++caa...........", ".........cc+++++#+cbbaaaaa......", "........cc+#+++#+cabbabbbaaa....", "......cc+#+++#+cc.aaabbbbbbaa...", "....cc+#+++#+cc....abbaaaabba...", "...c++#++#+cc......abba..aabba..", "...c+###++c........aabaa..aaba..", "....cc++cc..........abbaa..aba..", "......c.............aabbaaaaba..", ".....................baabbbbba..", ".......................aaaaaa...", "................................", "................................"}; PolyPickerSelection::PolyPickerSelection() { m_iRadius = 2; m_iNodes = 0; m_bWorking = false; } void PolyPickerSelection::initialize() { QPixmap p(cursor_cut_scissors); QCursor cursor(p, 4, 4); _pcView3D->getWidget()->setCursor(cursor); } void PolyPickerSelection::terminate() { // _pcView3D->getGLWidget()->releaseMouse(); } void PolyPickerSelection::draw () { if (mustRedraw){ if (_cNodeVector.size() > 1) { QPoint start = _cNodeVector.front(); for (std::vector::iterator it = _cNodeVector.begin()+1; it != _cNodeVector.end(); ++it) { _pcView3D->drawLine(start.x(),start.y(),it->x(), it->y() ); start = *it; } } // recursive call, but no infinite loop mustRedraw = false; draw(); } if (m_bWorking) { if (m_iNodes < int(_cNodeVector.size())) { m_iNodes = int(_cNodeVector.size()); if (_cNodeVector.size() > 2) { QPoint start = _cNodeVector.front(); _pcView3D->drawLine(m_iXnew,m_iYnew,start.x(), start.y() ); } } else { _pcView3D->drawLine(m_iXnew,m_iYnew,m_iXold,m_iYold); if (_cNodeVector.size() > 1) { QPoint start = _cNodeVector.front(); _pcView3D->drawLine(m_iXnew,m_iYnew,start.x(), start.y()); } } } } PolyPickerSelection::~PolyPickerSelection() { } int PolyPickerSelection::popupMenu() { QMenu menu; QAction* fi = menu.addAction(QObject::tr("Finish")); menu.addAction(QObject::tr("Clear")); QAction* ca = menu.addAction(QObject::tr("Cancel")); if (getPositions().size() < 3) fi->setEnabled(false); QAction* id = menu.exec(QCursor::pos()); if (id == fi) return Finish; else if (id == ca) return Cancel; else return Restart; } int PolyPickerSelection::mouseButtonEvent( const SoMouseButtonEvent * const e, const QPoint& pos ) { const int button = e->getButton(); const SbBool press = e->getState() == SoButtonEvent::DOWN ? TRUE : FALSE; if (press) { switch (button) { case SoMouseButtonEvent::BUTTON1: { // start working from now on if (!m_bWorking) { m_bWorking = true; // clear the old polygon _cNodeVector.clear(); _pcView3D->getGLWidget()->update(); // _pcView3D->getGLWidget()->grabMouse(); } _cNodeVector.push_back(pos); m_iXnew = pos.x(); m_iYnew = pos.y(); m_iXold = pos.x(); m_iYold = pos.y(); } break; case SoMouseButtonEvent::BUTTON2: { if (_cNodeVector.size() > 0) { if (_cNodeVector.back() != pos) _cNodeVector.push_back(pos); m_iXnew = pos.x(); m_iYnew = pos.y(); m_iXold = pos.x(); m_iYold = pos.y(); } QCursor cur = _pcView3D->getWidget()->cursor(); _pcView3D->getWidget()->setCursor(m_cPrevCursor); // _pcView3D->getGLWidget()->releaseMouse(); int id = popupMenu(); if (id == Finish || id == Cancel) { releaseMouseModel(); } else if (id == Restart) { m_bWorking = false; m_iNodes = 0; _pcView3D->getWidget()->setCursor(cur); } return id; } break; default: { } break; } } return Continue; } int PolyPickerSelection::locationEvent( const SoLocation2Event * const e, const QPoint& pos ) { // do all the drawing stuff for us QPoint clPoint = pos; if (m_bWorking) { // check the position QRect r = _pcView3D->getGLWidget()->rect(); if (!r.contains(clPoint)) { if (clPoint.x() < r.left()) clPoint.setX( r.left()); if (clPoint.x() > r.right()) clPoint.setX(r.right()); if (clPoint.y() < r.top()) clPoint.setY(r.top()); if (clPoint.y() > r.bottom()) clPoint.setY(r.bottom()); #ifdef FC_OS_WINDOWS QPoint newPos = _pcView3D->getGLWidget()->mapToGlobal(clPoint); QCursor::setPos(newPos); #endif } } draw(); m_iXnew = clPoint.x(); m_iYnew = clPoint.y(); draw(); return Continue; } int PolyPickerSelection::keyboardEvent( const SoKeyboardEvent * const e ) { return Continue; } // ----------------------------------------------------------------------------------- PolyClipSelection::PolyClipSelection() { } PolyClipSelection::~PolyClipSelection() { } int PolyClipSelection::popupMenu() { QMenu menu; QAction* ci = menu.addAction(QObject::tr("Inner")); QAction* co = menu.addAction(QObject::tr("Outer")); QAction* ca = menu.addAction(QObject::tr("Cancel")); if (getPositions().size() < 3) { ci->setEnabled(false); co->setEnabled(false); } QAction* id = menu.exec(QCursor::pos()); if (id == ci) { m_bInner = true; return Finish; } else if (id == co) { m_bInner = false; return Finish; } else if (id == ca) return Cancel; else return Restart; } // ----------------------------------------------------------------------------------- RectangleSelection::RectangleSelection() { m_bWorking = false; } RectangleSelection::~RectangleSelection() { } void RectangleSelection::initialize() { } void RectangleSelection::terminate() { } void RectangleSelection::draw () { if (m_bWorking) _pcView3D->drawRect(m_iXold, m_iYold, m_iXnew, m_iYnew); } int RectangleSelection::mouseButtonEvent( const SoMouseButtonEvent * const e, const QPoint& pos ) { const int button = e->getButton(); const SbBool press = e->getState() == SoButtonEvent::DOWN ? TRUE : FALSE; int ret = Continue; if (press) { switch ( button ) { case SoMouseButtonEvent::BUTTON1: { m_bWorking = true; m_iXold = m_iXnew = pos.x(); m_iYold = m_iYnew = pos.y(); } break; default: { } break; } } else { switch (button) { case SoMouseButtonEvent::BUTTON1: { releaseMouseModel(); m_bWorking = false; ret = Finish; } break; default: { } break; } } return ret; } int RectangleSelection::locationEvent( const SoLocation2Event * const e, const QPoint& pos ) { draw(); m_iXnew = pos.x(); m_iYnew = pos.y(); draw(); return Continue; } int RectangleSelection::keyboardEvent( const SoKeyboardEvent * const e ) { return Continue; } // ----------------------------------------------------------------------------------- BoxZoomSelection::BoxZoomSelection() { } BoxZoomSelection::~BoxZoomSelection() { } void BoxZoomSelection::terminate() { int xmin = std::min(m_iXold, m_iXnew); int xmax = std::max(m_iXold, m_iXnew); int ymin = std::min(m_iYold, m_iYnew); int ymax = std::max(m_iYold, m_iYnew); SbBox2s box(xmin, ymin, xmax, ymax); _pcView3D->boxZoom(box); }