void MapWidget::wheelEvent(QWheelEvent* event) { QPoint numPixels = event->pixelDelta(); QPoint numDegrees = event->angleDelta() / 8; int steps = 0; if (!numPixels.isNull()) { steps = numPixels.y()>0 ? numPixels.manhattanLength() : -numPixels.manhattanLength(); } else if (!numDegrees.isNull()) { QPoint numSteps = numDegrees / 15; steps = numSteps.y()>0 ? numSteps.manhattanLength() : -numSteps.manhattanLength(); } if(steps==0){ return; } if (steps>=0) { zoomIn(std::max(1.01,0.2*steps)); } else { zoomOut(std::max(1.01,0.2*steps)); } event->accept(); }
void SmoothImageMover::timerEvent(QTimerEvent * ev) { if ( ev->timerId() == m_moveTimerId ) { int dt = m_timer.elapsed(); m_velocity *= 0.8; m_timer.start(); QPoint delta = (m_velocity*dt).toPoint(); if ( !m_haveTargetPos && !m_allowedRect.contains(m_pos) ) { //get out of allowed area m_haveTargetPos = true; m_targetPos = m_pos; m_targetPos.setX( qBound( m_allowedRect.left(), m_pos.x(), m_allowedRect.right() ) ); m_targetPos.setY( qBound( m_allowedRect.top(), m_pos.y(), m_allowedRect.bottom() ) ); } if ( !m_allowedRect.contains(m_pos) ) { QPoint distance = m_targetPos - m_pos; if ( !distance.isNull() ) { QPointF gravitation = QPointF(distance)/distance.manhattanLength()/50; m_velocity += gravitation*dt; delta = (m_velocity * dt).toPoint(); if ( delta.manhattanLength() > distance.manhattanLength() ) { delta = distance/2; m_velocity = QPointF(distance/2)/dt; } } else { delta = QPoint(); m_velocity = QPointF(); } } m_pos += delta; bool finished = false; if ( delta.manhattanLength() < 4 ) { if ( !m_haveTargetPos ) finished = true; else { if ( (m_pos-m_targetPos).manhattanLength() < 16 ) { m_pos = m_targetPos; finished = true; } } } if ( finished ) { m_velocity = QPointF(0,0); killTimer(m_moveTimerId); m_moveTimerId = -1; } emit positionChanged( m_pos ); } }
bool RoutingLayerPrivate::handleMouseButtonRelease( QMouseEvent *e ) { if ( e->button() != Qt::LeftButton ) { return false; } if ( m_movingIndex >= 0 ) { m_movingIndex = -1; clearStopOver(); m_marbleWidget->model()->routingManager()->retrieveRoute(); return true; } if ( !m_dropStopOver.isNull() && !m_dragStopOver.isNull() ) { QPoint moved = e->pos() - m_dragStopOver; if ( moved.manhattanLength() < 10 ) { return false; } qreal lon( 0.0 ), lat( 0.0 ); if ( m_dragStopOverRightIndex >= 0 && m_dragStopOverRightIndex <= m_routeRequest->size() && m_marbleWidget->geoCoordinates( m_dropStopOver.x(), m_dropStopOver.y(), lon, lat, GeoDataCoordinates::Radian ) ) { GeoDataCoordinates position( lon, lat ); m_dragStopOverRightIndex = viaInsertPosition( e->modifiers() ); m_routeRequest->insert( m_dragStopOverRightIndex, position ); clearStopOver(); m_marbleWidget->model()->routingManager()->retrieveRoute(); return true; } } return false; }
void MrmlViewItem::mouseMoveEvent( QMouseEvent *e ) { if ( hitsPixmap( e->pos() ) ) { if ( !ownCursor() ) { // nice hacklet :) setCursor( KCursor::handCursor() ); emit view()->onItem( m_url ); } } else { if ( ownCursor() ) { unsetCursor(); emit view()->onItem( KURL() ); } } if ( (e->state() & LeftButton) && !pressedPos.isNull() ) { QPoint dist = e->pos() - pressedPos; if ( dist.manhattanLength() > KGlobalSettings::dndEventDelay() ) { // start drag here KURL::List urls; // ### support multiple files? urls.append( m_url ); KURLDrag *drag = new KURLDrag( urls, this ); drag->setPixmap( KMimeType::pixmapForURL( m_url ) ); drag->drag(); } } }
KJS::Value Point::call( KJS::ExecState *exec, KJS::Object &self, const KJS::List &args ) { if( !JSProxy::checkType(self, JSProxy::ValueProxy, "QPoint") ) return KJS::Value(); JSValueProxy *vp = JSProxy::toValueProxy( self.imp() ); KJS::Value retValue = KJS::Value(); QPoint val = vp->toVariant().toPoint(); switch ( mid ) { case Methodx: retValue = KJS::Number(val.x()); break; case MethodsetX: val.setX(extractInt(exec,args,0)); break; case Methody: retValue = KJS::Number(val.y()); break; case MethodsetY: val.setY(extractInt(exec,args,0)); break; case MethodmanhattanLength: retValue = KJS::Number(val.manhattanLength()); break; default: QString msg = i18n( "Point has no method %1" ).arg(mid); return throwError(exec, msg); break; } vp->setValue(val); return retValue; }
void ThemeContentItemSourceLabel::mouseMoveEvent( QMouseEvent * e ) { if ( e->buttons() & Qt::LeftButton ) { QPoint diff = mMousePressPoint - e->pos(); if ( diff.manhattanLength() > 4 ) startDrag(); } }
void MrmlViewItem::mouseReleaseEvent( QMouseEvent *e ) { if ( hitsPixmap( e->pos() )) { QPoint dist = e->pos() - pressedPos; if ( dist.manhattanLength() < KGlobalSettings::dndEventDelay() ) { emit view()->activated( m_url, e->button() ); } } }
void AbstractScopeWidget::mouseMoveEvent(QMouseEvent *event) { m_mousePos = event->pos(); m_mouseWithinWidget = true; emit signalMousePositionChanged(); QPoint movement = event->pos()-m_rescaleStartPoint; if (m_rescaleActive) { if (m_rescalePropertiesLocked) { // Direction is known, now adjust parameters // Reset the starting point to make the next moveEvent relative to the current one m_rescaleStartPoint = event->pos(); if (!m_rescaleFirstRescaleDone) { // We have just learned the desired direction; Normalize the movement to one pixel // to avoid a jump by m_rescaleMinDist if (movement.x() != 0) { movement.setX(movement.x() / abs(movement.x())); } if (movement.y() != 0) { movement.setY(movement.y() / abs(movement.y())); } m_rescaleFirstRescaleDone = true; } handleMouseDrag(movement, m_rescaleDirection, m_rescaleModifiers); } else { // Detect the movement direction here. // This algorithm relies on the aspect ratio of dy/dx (size and signum). if (movement.manhattanLength() > m_rescaleMinDist) { float diff = ((float) movement.y())/movement.x(); if (fabs(diff) > m_rescaleVerticalThreshold || movement.x() == 0) { m_rescaleDirection = North; } else if (fabs(diff) < 1/m_rescaleVerticalThreshold) { m_rescaleDirection = East; } else if (diff < 0) { m_rescaleDirection = Northeast; } else { m_rescaleDirection = Southeast; } #ifdef DEBUG_ASW qDebug() << "Diff is " << diff << "; chose " << directions[m_rescaleDirection] << " as direction"; #endif m_rescalePropertiesLocked = true; } } } }
bool Screen::isBottomRight(const Screen &screen) const { QPoint distancePoint = m_geometry.topLeft() - screen.getGeometry().bottomRight(); if (distancePoint.manhattanLength() < MaximumDistanceInBetween) { return true; } return false; }
void CMapWidget::mouseMoveEvent(QMouseEvent *event) { if (!m_map || !m_patches) return; event->accept(); // Figure out the hovered position const QPoint &rawScreenPos = event->pos(); CMapPoint newHover = calculateClickedPosition(rawScreenPos); // If it hasn't changed, do nothing! if (!(hovered == newHover)) { // Mark the old position as modified, if it was valid if (isHovering) updateTile(hovered, CEditableMap::HighlightUpdate); bool newFlag = m_map->positionValid(newHover); // before we clobber "hovered", call the tool's hoverstatus emit hoverStatusChanged(isHovering, hovered, newFlag, newHover, event); m_currentTool->hoverStatusChanged(isHovering, hovered, newFlag, newHover, event); // now update + write the new position's info isHovering = newFlag; hovered = newHover; if (newFlag) updateTile(newHover, CEditableMap::HighlightUpdate); } // Now, do drag processing! if (m_isDraggingMap && m_scrollArea) { // translate this position to the one clicked on-screen, // not the position in "world space" ... this is a bad explanation // oh well QPoint scrollOffset = QPoint(m_scrollArea->horizontalScrollBar()->value(), m_scrollArea->verticalScrollBar()->value()); QPoint newPos = rawScreenPos - scrollOffset; // now that they're both on the same base, the delta is easy to figure // out QPoint delta = newPos - m_dragStart; delta *= 1.5f; m_roughDragDistance += delta.manhattanLength(); QPoint newOffset = scrollOffset - delta; m_scrollArea->horizontalScrollBar()->setValue(newOffset.x()); m_scrollArea->verticalScrollBar()->setValue(newOffset.y()); m_dragStart = newPos; } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RiuViewer::mouseReleaseEvent(QMouseEvent* event) { m_mouseState.updateFromMouseEvent(event); if (!this->canRender()) return; // Picking if (event->button() == Qt::LeftButton) { handlePickAction(event->x(), event->y()); return; } else if (event->button() == Qt::RightButton) { m_currentGridIdx = cvf::UNDEFINED_SIZE_T; m_currentCellIndex = cvf::UNDEFINED_SIZE_T; QPoint diffPoint = event->pos() - m_lastMousePressPosition; if (diffPoint.manhattanLength() > 3) { // We are possibly in navigation mode, only clean press event will launch return; } int winPosX = event->x(); int winPosY = event->y(); uint faceIndex = cvf::UNDEFINED_UINT; cvf::Vec3d localIntersectionPoint(cvf::Vec3d::ZERO); cvf::Part * firstHitPart = NULL; firstHitPart = pickPointAndFace(winPosX, winPosY, &faceIndex, &localIntersectionPoint); if (firstHitPart) { if (faceIndex != cvf::UNDEFINED_UINT) { if (firstHitPart->sourceInfo()) { const cvf::Array<size_t>* cellIndices = dynamic_cast<const cvf::Array<size_t>*>(firstHitPart->sourceInfo()); if (cellIndices) { m_currentGridIdx = firstHitPart->id(); m_currentCellIndex = cellIndices->get(faceIndex); QMenu menu; menu.addAction(QString("I-slice range filter"), this, SLOT(slotRangeFilterI())); menu.addAction(QString("J-slice range filter"), this, SLOT(slotRangeFilterJ())); menu.addAction(QString("K-slice range filter"), this, SLOT(slotRangeFilterK())); menu.exec(event->globalPos()); } } } } } }
void DragBarButton::mouseMoveEvent( QMouseEvent* ev ) { if (m_bPressed) { QPoint p = m_ppoint; p -= ev->pos(); if (p.manhattanLength() > 2 && !m_bDragged ) { m_bDragged = true; emit beginDrag(); } } }
QGestureRecognizer::Result QTapAndHoldGestureRecognizer::recognize(QGesture *state, QObject *object, QEvent *event) { QTapAndHoldGesture *q = static_cast<QTapAndHoldGesture *>(state); QTapAndHoldGesturePrivate *d = q->d_func(); if (object == state && event->type() == QEvent::Timer) { q->killTimer(d->timerId); d->timerId = 0; return QGestureRecognizer::Ignore | QGestureRecognizer::ConsumeEventHint; } const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture; enum { TimerInterval = 2000 }; enum { TapRadius = 40 }; switch (event->type()) { case QEvent::TouchBegin: d->position = ev->touchPoints().at(0).pos(); if (d->timerId) q->killTimer(d->timerId); d->timerId = q->startTimer(TimerInterval); result = QGestureRecognizer::TriggerGesture; break; case QEvent::TouchEnd: if (d->timerId) result = QGestureRecognizer::CancelGesture; else result = QGestureRecognizer::FinishGesture; break; case QEvent::TouchUpdate: if (q->state() != Qt::NoGesture && ev->touchPoints().size() == 1) { QTouchEvent::TouchPoint p = ev->touchPoints().at(0); QPoint delta = p.pos().toPoint() - p.startPos().toPoint(); if (delta.manhattanLength() <= TapRadius) result = QGestureRecognizer::TriggerGesture; } break; case QEvent::MouseButtonPress: case QEvent::MouseMove: case QEvent::MouseButtonRelease: result = QGestureRecognizer::Ignore; break; default: result = QGestureRecognizer::Ignore; break; } return result; }
QGestureRecognizer::Result WebosTapAndHoldGestureRecognizer::recognize(QGesture *state, QObject *object, QEvent *event) { QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture; WebosTapAndHoldGesture *q = static_cast<WebosTapAndHoldGesture *>(state); if (object == state && event->type() == QEvent::Timer) { q->stopTapTimer(); if (q->state() != Qt::NoGesture && q->state() != Qt::GestureCanceled) { result = QGestureRecognizer::FinishGesture; } return result | QGestureRecognizer::ConsumeEventHint; } const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); //Todo Here use a const value to set up the timer interval but maybe need to use the Timeout value //enum { TimerInterval = 700 }; enum { TapRadius = 40 }; switch (event->type()) { case QEvent::TouchBegin: q->setPosition(ev->touchPoints().at(0).startScreenPos()); q->setHotSpot(q->position()); q->stopTapTimer(); q->startTapTimer(); return QGestureRecognizer::TriggerGesture; case QEvent::TouchEnd: result = QGestureRecognizer::CancelGesture; q->stopTapTimer(); break; case QEvent::TouchUpdate: if (q->tapTimerId() && ev->touchPoints().size() == 1) { QTouchEvent::TouchPoint p = ev->touchPoints().at(0); QPoint delta = p.pos().toPoint() - p.startPos().toPoint(); if (delta.manhattanLength() > TapRadius) { result = QGestureRecognizer::CancelGesture; q->stopTapTimer(); } else { result = QGestureRecognizer::Ignore; } } else if (ev->touchPoints().size() > 1) { result = QGestureRecognizer::CancelGesture; q->stopTapTimer(); } else { result = QGestureRecognizer::Ignore; } break; default: return QGestureRecognizer::Ignore; } return result; }
void DraggableListView::mouseMoveEvent(QMouseEvent *e) { if (_dragEnabled && e->buttons() & Qt::LeftButton && _pressPos != QPoint(-1, -1)) { QPoint delta = e->pos() - _pressPos; if (delta.manhattanLength() > QApplication::startDragDistance()) { _pressPos = QPoint(-1, -1); startDrag(); } e->accept(); } else { Q3ListView::mouseMoveEvent(e); } }
void CSMonitorClient::mouseMoveEvent(QMouseEvent *event) { if(m_bPressed) { QPoint movePos = event->globalPos() - m_movePoint; int distance = movePos.manhattanLength(); bool bMoved = distance > QApplication::startDragDistance() ? true : false; if(bMoved) { this->move(movePos); } } }
void FlagList::removeNearestFlag(const QPoint &target, int w, int h, int offset) { Flag *flag = 0; QPoint diff; int dist = INT_MAX; QPtrListIterator<Flag> it(_flags); for ( ; it.current(); ++it) { diff = getPosition(it.current()->latitude(), it.current()->longitude(), w, h, offset); diff -= target; if (diff.manhattanLength() < dist) { dist = diff.manhattanLength(); flag = it.current(); } } if (flag) _flags.remove(flag); }
void CQCustomInputHandler::mouseReleaseEvent(QMouseEvent * event, const QPoint & mousePos) { mState = CQCustomInputHandler::StateNormal; if (event->button() == Qt::RightButton) { QPoint diff = mousePos - mPosDown; if (diff.manhattanLength() < 5) emit signalShowContextMenu(mousePos); } Q3DInputHandler::mouseReleaseEvent(event, mousePos); }
void PluginWidget::mousePressEvent(QMouseEvent *e) { if (e->button() != Qt::RightButton) return QWidget::mousePressEvent(e); const QPoint p(e->pos() - rect().center()); if (p.manhattanLength() < std::min(width(), height()) * 0.8 * 0.5) { emit requestContextMenu(SHUTDOWN_KEY); return; } return QWidget::mousePressEvent(e); }
void KoColorPanel::mouseMoveEvent( QMouseEvent* e ) { if ( e->state() & Qt::LeftButton ) { QPoint p = m_pressedPos - e->pos(); if ( p.manhattanLength() > QApplication::startDragDistance() ) { QColor color( mapToColor( m_pressedPos ) ); if ( color.isValid() ) { KColorDrag *drag = new KColorDrag( color, this, name() ); drag->dragCopy(); } } } else updateFocusPosition( mapToPosition( e->pos() ) ); }
void FlickCharm::timerEvent(QTimerEvent *event) { // qDebug() << __FUNCTION__ << "timer" << m_count << m_speed << m_count * m_speed; m_count++; // 0..100 -> 0..1 scrollTo(m_releasePos + m_speed / MULT); // create unit vector QPoint unit = MULT * m_speed / m_speed.manhattanLength(); if(m_count >= 1000 || unit.manhattanLength() > m_speed.manhattanLength()) m_timer.stop(); else m_speed -= unit; QObject::timerEvent(event); }
bool PicItem::mouseMoveEvent( const EventInfo &info ) { QMouseEvent *e = info.mouseMoveEvent( 0, 0 ); const PinItemList::iterator end = m_pinItemList.end(); for ( PinItemList::iterator it = m_pinItemList.begin(); it != end; ++it ) if ( e->isAccepted() && (*it)->boundingRect().contains( info.pos ) ) { QPoint vec = info.pos - m_pos; if ( m_pressed && vec.manhattanLength() > 4 ) { m_dragged = true; m_dx = vec.x(); } delete e; return true; } delete e; return CNItem::mouseMoveEvent( info ); }
bool UBMousePressFilter::eventFilter(QObject *obj, QEvent *event) { const bool isMousePress = event->type() == QEvent::MouseButtonPress; const bool isMouseRelease = event->type() == QEvent::MouseButtonRelease; const bool isMouseMove = event->type() == QEvent::MouseMove; if (isMousePress) { QMouseEvent * mouseEvent = static_cast<QMouseEvent *>(event); if (mouseEvent) { if (mPendingEvent) { delete mPendingEvent; } mPendingEvent = new QMouseEvent(QEvent::MouseButtonDblClick, mouseEvent->pos(), mouseEvent->globalPos(), mouseEvent->button(), mouseEvent->buttons(), mouseEvent->modifiers()); mObject = obj; QTimer::singleShot(1000, this, SLOT(mouseDownElapsed())); } } else if (isMouseRelease || isMouseMove) { if (mPendingEvent) { QTabletEvent * tabletEvent = static_cast<QTabletEvent *>(event); QPoint point = tabletEvent->globalPos() - mPendingEvent->globalPos(); if (isMouseRelease || point.manhattanLength() > QApplication::startDragDistance()) { delete mPendingEvent; mPendingEvent = 0; mObject = 0; } } } return false; }
QGestureRecognizer::Result QTapGestureRecognizer::recognize(QGesture *state, QObject *, QEvent *event) { QTapGesture *q = static_cast<QTapGesture *>(state); QTapGesturePrivate *d = q->d_func(); const QTouchEvent *ev = static_cast<const QTouchEvent *>(event); QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture; switch (event->type()) { case QEvent::TouchBegin: { d->position = ev->touchPoints().at(0).pos(); q->setHotSpot(ev->touchPoints().at(0).screenPos()); result = QGestureRecognizer::TriggerGesture; break; } case QEvent::TouchUpdate: case QEvent::TouchEnd: { if (q->state() != Qt::NoGesture && ev->touchPoints().size() == 1) { QTouchEvent::TouchPoint p = ev->touchPoints().at(0); QPoint delta = p.pos().toPoint() - p.startPos().toPoint(); enum { TapRadius = 40 }; if (delta.manhattanLength() <= TapRadius) { if (event->type() == QEvent::TouchEnd) result = QGestureRecognizer::FinishGesture; else result = QGestureRecognizer::TriggerGesture; } } break; } case QEvent::MouseButtonPress: case QEvent::MouseMove: case QEvent::MouseButtonRelease: result = QGestureRecognizer::Ignore; break; default: result = QGestureRecognizer::Ignore; break; } return result; }
int CurveGroup::getActiveMorphedCurve(int key, int v0, int v1) { for(int m=0; m<m_mcg.count(); m++) { if (m_mcg[m].contains(key)) { Curve c = m_mcg[m].value(key); QPoint cen = QPoint(v0, v1); int npts = c.pts.count(); for(int i=npts-1; i>=0; i--) { QPoint v = c.pts[i] - cen; if (v.manhattanLength() < 5) return m; } } } return -1; }
void CMoveWidget::mouseMoveEvent(QMouseEvent *mouseEvent) { QPoint p = mouseEvent->globalPos() - dragStartMousePosition; if (p.manhattanLength() < QApplication::startDragDistance()) return; QPoint r = dragStartWidgetPosition + p; if (r.x() < 0) r.setX(0); if (r.y() < 0) r.setY(0); int maxW = this->parentWidget()->geometry().width() - this->geometry().width(); int maxH = this->parentWidget()->geometry().height() - this->geometry().height(); if (r.rx() > maxW) r.setX(maxW); if (r.ry() > maxH) r.setY(maxH); move(r); QWidget::mouseMoveEvent(mouseEvent); }
int CurveGroup::getActiveCurve(int key, int v0, int v1) { if (!m_cg.contains(key)) return -1; QList<Curve*> curves = m_cg.values(key); for(int ic=0; ic<curves.count(); ic++) { QPoint cen = QPoint(v0, v1); int npts = curves[ic]->pts.count(); for(int i=npts-1; i>=0; i--) { QPoint v = curves[ic]->pts[i] - cen; if (v.manhattanLength() < 3) return ic; } } return -1; }
void AnalogPad::mouseMoveEvent(QMouseEvent *event) { // Return if mouse was not pressed inside the pad area if(!m_MouseDown) return; if(m_MouseClick) { QPoint d = event->pos() - m_TouchPosition; if(d.manhattanLength()>4) m_MouseClick = false; } if (!m_MouseClick) { // Scale pad position to range [-1, 1] qreal xx = qreal(event->pos().x()) / m_Position.x() - 1; qreal yy = qreal(event->pos().y()) / m_Position.y() - 1; // Calculate the distance from the center qreal dist = sqrt(pow(xx, 2) + pow(yy, 2)); // Calculate unit vectors xx/=dist; yy/=dist; // Check if the distance from the center exceeds maximum if(dist>MAX_DIST) { dist = MAX_DIST; m_LimitReached = true; } else { m_LimitReached = false; } // Calculate new pad position QPoint newpos((xx*dist + 1) * m_Position.x(), (yy*dist + 1)*m_Position.y()); setPadPosition(newpos); update(); emitValueChanged(); } }
void Card::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() == Qt::LeftButton && okToMove) { Card *temp = NULL; // remember to set pointers to NULL or your game will crash QPoint point = event->globalPos() + mouseDownOffset; QPoint moved = point - pos(); if (moved.manhattanLength() > 4) moving = pile->checkDragRules(this); if (moving) { this->move(point); this->raise(); if (this->over) temp = this->over; while (temp) { point += myPile()->Delta(); temp->raise(); temp->move(point); temp = temp->over; } } } }
void CurveGroup::removePoint(int key, int v0, int v1) { int ic = getActiveCurve(key, v0, v1); if (ic < 0) return; m_pointsDirtyBit = true; QList<Curve*> curves = m_cg.values(key); QPoint cen = QPoint(v0, v1); int npts = curves[ic]->pts.count(); for(int i=npts-1; i>=0; i--) { QPoint v = curves[ic]->pts[i] - cen; if (v.manhattanLength() < 3) { curves[ic]->pts.remove(i, curves[ic]->pts.count()-i); if (curves[ic]->pts.count() == 0) { // remove related morphed curves int mc = getActiveMorphedCurve(key, curves[ic]->pts[0].x(), curves[ic]->pts[0].y()); if (mc >= 0) m_mcg.removeAt(mc); delete curves[ic]; curves.removeAt(ic); m_cg.remove(key); for(int j=0; j<curves.count(); j++) m_cg.insert(key, curves[j]); } return; } } }