diff --git a/ApplicationLibCode/UserInterface/CMakeLists_files.cmake b/ApplicationLibCode/UserInterface/CMakeLists_files.cmake index e8361f003b..d160e40079 100644 --- a/ApplicationLibCode/UserInterface/CMakeLists_files.cmake +++ b/ApplicationLibCode/UserInterface/CMakeLists_files.cmake @@ -313,7 +313,6 @@ list( ${CMAKE_CURRENT_LIST_DIR}/RiuTextContentFrame.h ${CMAKE_CURRENT_LIST_DIR}/RiuQwtLegendOverlayContentFrame.h ${CMAKE_CURRENT_LIST_DIR}/RiuMatrixPlotWidget.h - ${CMAKE_CURRENT_LIST_DIR}/RiuQwtPlotZoomerMultiAxes.h ) list(APPEND QT_UI_FILES) diff --git a/ApplicationLibCode/UserInterface/RiuQwtPlotZoomer.h b/ApplicationLibCode/UserInterface/RiuQwtPlotZoomer.h index 0aacb1f4a5..4bbdd414ca 100644 --- a/ApplicationLibCode/UserInterface/RiuQwtPlotZoomer.h +++ b/ApplicationLibCode/UserInterface/RiuQwtPlotZoomer.h @@ -47,8 +47,6 @@ class RiuQwtPlotZoomer : public RiuQwtPlotZoomerMultiAxes void endZoomOperation() { reset(); } protected: - QSizeF minZoomSize() const override { return RiuQwtPlotZoomerMultiAxes::minZoomSize() / 10.0e6; } - bool accept( QPolygon& pa ) const override { if ( pa.count() < 2 ) return false; diff --git a/ApplicationLibCode/UserInterface/RiuQwtPlotZoomerMultiAxes.cpp b/ApplicationLibCode/UserInterface/RiuQwtPlotZoomerMultiAxes.cpp index b26c259cb3..b83cdc2993 100644 --- a/ApplicationLibCode/UserInterface/RiuQwtPlotZoomerMultiAxes.cpp +++ b/ApplicationLibCode/UserInterface/RiuQwtPlotZoomerMultiAxes.cpp @@ -1,686 +1,110 @@ -/****************************************************************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight 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 General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// #include "RiuQwtPlotZoomerMultiAxes.h" -#include "qwt_interval.h" #include "qwt_picker_machine.h" #include "qwt_plot.h" -#include "qwt_plot_zoomer.h" #include "qwt_scale_div.h" #include "qwt_scale_map.h" -#include - -#pragma optimize( "", off ) - -static QwtInterval qwtExpandedZoomInterval( double v1, double v2, double minRange, const QwtTransform* transform ) -{ - double min = v1; - double max = v2; - - if ( max - min < minRange ) - { - min = 0.5 * ( min + max - minRange ); - max = min + minRange; - - if ( transform ) - { - // f.e the logarithmic scale doesn't allow values - // outside [QwtLogTransform::LogMin/QwtLogTransform::LogMax] - - double minBounded = transform->bounded( min ); - double maxBounded = transform->bounded( max ); - - if ( minBounded != min ) - { - maxBounded = transform->bounded( minBounded + minRange ); - } - else if ( maxBounded != max ) - { - minBounded = transform->bounded( maxBounded - minRange ); - } - - min = minBounded; - max = maxBounded; - } - } - - return QwtInterval( min, max ); -} - -static QRectF qwtExpandedZoomRect( const QRectF& zoomRect, const QSizeF& minSize, const QwtTransform* transformX, const QwtTransform* transformY ) -{ - QRectF r = zoomRect; - - if ( minSize.width() > r.width() ) - { - const QwtInterval intv = qwtExpandedZoomInterval( r.left(), r.right(), minSize.width(), transformX ); - - r.setLeft( intv.minValue() ); - r.setRight( intv.maxValue() ); - } - - if ( minSize.height() > r.height() ) - { - const QwtInterval intv = qwtExpandedZoomInterval( zoomRect.top(), zoomRect.bottom(), minSize.height(), transformY ); - - r.setTop( intv.minValue() ); - r.setBottom( intv.maxValue() ); - } - - return r; -} - -class RiuQwtPlotZoomerMultiAxes::PrivateData -{ -public: - uint zoomRectIndex; - QStack zoomStack; - QRectF rectInScreenCoords; - - int maxStackDepth; -}; - -/*! - \brief Create a zoomer for a plot canvas. - - The zoomer is set to those x- and y-axis of the parent plot of the - canvas that are enabled. If both or no x-axis are enabled, the picker - is set to QwtAxis::XBottom. If both or no y-axis are - enabled, it is set to QwtAxis::YLeft. - - The zoomer is initialized with a QwtPickerDragRectMachine, - the tracker mode is set to QwtPicker::ActiveOnly and the rubber band - is set to QwtPicker::RectRubberBand - - \param canvas Plot canvas to observe, also the parent object - \param doReplot Call QwtPlot::replot() for the attached plot before initializing - the zoomer with its scales. This might be necessary, - when the plot is in a state with pending scale changes. - - \sa QwtPlot::autoReplot(), QwtPlot::replot(), setZoomBase() - */ +//-------------------------------------------------------------------------------------------------- +/// Create a zoomer for a plot canvas. All axes will be scaled based on the rectangle in screen coordinates. +//-------------------------------------------------------------------------------------------------- RiuQwtPlotZoomerMultiAxes::RiuQwtPlotZoomerMultiAxes( QWidget* canvas, bool doReplot ) : QwtPlotPicker( canvas ) { - if ( canvas ) init( doReplot ); -} - -/*! - \brief Create a zoomer for a plot canvas. - - The zoomer is initialized with a QwtPickerDragRectMachine, - the tracker mode is set to QwtPicker::ActiveOnly and the rubber band - is set to QwtPicker::RectRubberBand - - \param xAxisId X axis of the zoomer - \param yAxisId Y axis of the zoomer - \param canvas Plot canvas to observe, also the parent object - \param doReplot Call QwtPlot::replot() for the attached plot before initializing - the zoomer with its scales. This might be necessary, - when the plot is in a state with pending scale changes. - - \sa QwtPlot::autoReplot(), QwtPlot::replot(), setZoomBase() - */ - -RiuQwtPlotZoomerMultiAxes::RiuQwtPlotZoomerMultiAxes( QwtAxisId xAxisId, QwtAxisId yAxisId, QWidget* canvas, bool doReplot ) - : QwtPlotPicker( xAxisId, yAxisId, canvas ) -{ - if ( canvas ) init( doReplot ); -} - -//! Init the zoomer, used by the constructors -void RiuQwtPlotZoomerMultiAxes::init( bool doReplot ) -{ - m_data = new PrivateData; - - m_data->maxStackDepth = -1; - - setTrackerMode( ActiveOnly ); - setRubberBand( RectRubberBand ); - setStateMachine( new QwtPickerDragRectMachine() ); - - if ( doReplot && plot() ) plot()->replot(); - - setZoomBase( scaleRect() ); -} - -RiuQwtPlotZoomerMultiAxes::~RiuQwtPlotZoomerMultiAxes() -{ - delete m_data; -} - -/*! - \brief Limit the number of recursive zoom operations to depth. - - A value of -1 set the depth to unlimited, 0 disables zooming. - If the current zoom rectangle is below depth, the plot is unzoomed. - - \param depth Maximum for the stack depth - \sa maxStackDepth() - \note depth doesn't include the zoom base, so zoomStack().count() might be - maxStackDepth() + 1. - */ -void RiuQwtPlotZoomerMultiAxes::setMaxStackDepth( int depth ) -{ - m_data->maxStackDepth = depth; - - if ( depth >= 0 ) - { - // unzoom if the current depth is below m_data->maxStackDepth - - const int zoomOut = m_data->zoomStack.count() - 1 - depth; // -1 for the zoom base - - if ( zoomOut > 0 ) - { - zoom( -zoomOut ); - for ( int i = m_data->zoomStack.count() - 1; i > int( m_data->zoomRectIndex ); i-- ) - { - (void)m_data->zoomStack.pop(); // remove trailing rects - } - } - } -} - -/*! - \return Maximal depth of the zoom stack. - \sa setMaxStackDepth() - */ -int RiuQwtPlotZoomerMultiAxes::maxStackDepth() const -{ - return m_data->maxStackDepth; -} - -/*! - \return The zoom stack. zoomStack()[0] is the zoom base, - zoomStack()[1] the first zoomed rectangle. - - \sa setZoomStack(), zoomRectIndex() - */ -const QStack& RiuQwtPlotZoomerMultiAxes::zoomStack() const -{ - return m_data->zoomStack; -} - -/*! - \return Initial rectangle of the zoomer - \sa setZoomBase(), zoomRect() - */ -QRectF RiuQwtPlotZoomerMultiAxes::zoomBase() const -{ - return m_data->zoomStack[0]; -} - -/*! - Reinitialized the zoom stack with scaleRect() as base. - - \param doReplot Call QwtPlot::replot() for the attached plot before initializing - the zoomer with its scales. This might be necessary, - when the plot is in a state with pending scale changes. - - \sa zoomBase(), scaleRect() QwtPlot::autoReplot(), QwtPlot::replot(). - */ -void RiuQwtPlotZoomerMultiAxes::setZoomBase( bool doReplot ) -{ - QwtPlot* plt = plot(); - if ( plt == NULL ) return; - - if ( doReplot ) plt->replot(); - - m_data->zoomStack.clear(); - m_data->zoomStack.push( scaleRect() ); - m_data->zoomRectIndex = 0; - - rescale(); -} - -/*! - \brief Set the initial size of the zoomer. - - base is united with the current scaleRect() and the zoom stack is - reinitialized with it as zoom base. plot is zoomed to scaleRect(). - - \param base Zoom base - - \sa zoomBase(), scaleRect() - */ -void RiuQwtPlotZoomerMultiAxes::setZoomBase( const QRectF& base ) -{ - const QwtPlot* plt = plot(); - if ( !plt ) return; - - const QRectF sRect = scaleRect(); - const QRectF bRect = base | sRect; - - m_data->zoomStack.clear(); - m_data->zoomStack.push( bRect ); - m_data->zoomRectIndex = 0; - - if ( base != sRect ) + if ( canvas ) { - m_data->zoomStack.push( sRect ); - m_data->zoomRectIndex++; - } - - rescale(); -} - -/*! - \return Rectangle at the current position on the zoom stack. - \sa zoomRectIndex(), scaleRect(). - */ -QRectF RiuQwtPlotZoomerMultiAxes::zoomRect() const -{ - return m_data->zoomStack[m_data->zoomRectIndex]; -} - -/*! - \return Index of current position of zoom stack. - */ -uint RiuQwtPlotZoomerMultiAxes::zoomRectIndex() const -{ - return m_data->zoomRectIndex; -} - -/*! - \brief Zoom in - - Clears all rectangles above the current position of the - zoom stack and pushes the normalized rectangle on it. + setTrackerMode( ActiveOnly ); + setRubberBand( RectRubberBand ); + setStateMachine( new QwtPickerDragRectMachine() ); - \note If the maximal stack depth is reached, zoom is ignored. - \note The zoomed signal is emitted. - */ - -void RiuQwtPlotZoomerMultiAxes::zoom( const QRectF& rect ) -{ - if ( m_data->maxStackDepth >= 0 && int( m_data->zoomRectIndex ) >= m_data->maxStackDepth ) - { - return; - } - - const QRectF zoomRect = rect.normalized(); - if ( zoomRect != m_data->zoomStack[m_data->zoomRectIndex] ) - { - for ( uint i = m_data->zoomStack.count() - 1; i > m_data->zoomRectIndex; i-- ) - { - (void)m_data->zoomStack.pop(); - } - - m_data->zoomStack.push( zoomRect ); - m_data->zoomRectIndex++; - - rescale(); - - Q_EMIT zoomed( zoomRect ); + if ( doReplot && plot() ) plot()->replot(); } } -/*! - \brief Zoom in or out - - Activate a rectangle on the zoom stack with an offset relative - to the current position. Negative values of offset will zoom out, - positive zoom in. A value of 0 zooms out to the zoom base. - - \param offset Offset relative to the current position of the zoom stack. - \note The zoomed signal is emitted. - \sa zoomRectIndex() - */ -void RiuQwtPlotZoomerMultiAxes::zoom( int offset ) -{ - int newIndex; - - if ( offset == 0 ) - { - newIndex = 0; - } - else - { - newIndex = m_data->zoomRectIndex + offset; - newIndex = qBound( 0, newIndex, m_data->zoomStack.count() - 1 ); - } - - if ( newIndex != static_cast( m_data->zoomRectIndex ) ) - { - m_data->zoomRectIndex = newIndex; - rescale(); - Q_EMIT zoomed( zoomRect() ); - } -} - -/*! - \brief Assign a zoom stack - - In combination with other types of navigation it might be useful to - modify to manipulate the complete zoom stack. - - \param zoomStack New zoom stack - \param zoomRectIndex Index of the current position of zoom stack. - In case of -1 the current position is at the top - of the stack. - - \note The zoomed signal might be emitted. - \sa zoomStack(), zoomRectIndex() - */ -void RiuQwtPlotZoomerMultiAxes::setZoomStack( const QStack& zoomStack, int zoomRectIndex ) +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RiuQwtPlotZoomerMultiAxes::end( bool ok ) { - if ( zoomStack.isEmpty() ) return; - - if ( m_data->maxStackDepth >= 0 && zoomStack.count() > m_data->maxStackDepth ) - { - return; - } - - if ( zoomRectIndex < 0 || zoomRectIndex > zoomStack.count() ) zoomRectIndex = zoomStack.count() - 1; - - const bool doRescale = zoomStack[zoomRectIndex] != zoomRect(); - - m_data->zoomStack = zoomStack; - m_data->zoomRectIndex = uint( zoomRectIndex ); - - if ( doRescale ) - { - rescale(); - Q_EMIT zoomed( zoomRect() ); - } -} - -/*! - Adjust the observed plot to zoomRect() - - \note Initiates QwtPlot::replot() - */ + ok = QwtPlotPicker::end( ok ); + if ( !ok ) return false; -void RiuQwtPlotZoomerMultiAxes::rescale() -{ QwtPlot* plot = RiuQwtPlotZoomerMultiAxes::plot(); - if ( !plot ) return; - - const QRectF& rect = m_data->rectInScreenCoords; - // const QRectF& rect = m_data->zoomStack[m_data->zoomRectIndex]; - // if ( rect != scaleRect() ) - { - const bool doReplot = plot->autoReplot(); - plot->setAutoReplot( false ); - - for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ ) - { - const int axesCount = plot->axesCount( axisPos ); - for ( int i = 0; i < axesCount; i++ ) - { - const QwtAxisId axisId( axisPos, i ); - - const QwtScaleMap map = plot->canvasMap( axisId ); - - if ( axisId.isXAxis() ) - { - const double screenX1 = rect.left(); - const double screenX2 = rect.right(); - double domainX1 = map.invTransform( screenX1 ); - double domainX2 = map.invTransform( screenX2 ); - if ( !plot->axisScaleDiv( axisId ).isIncreasing() ) qSwap( domainX1, domainX2 ); - - plot->setAxisScale( axisId, domainX1, domainX2 ); - } - else - { - const double screenY1 = rect.top(); - const double screenY2 = rect.bottom(); - double domainY1 = map.invTransform( screenY1 ); - double domainY2 = map.invTransform( screenY2 ); - if ( plot->axisScaleDiv( axisId ).isIncreasing() ) qSwap( domainY1, domainY2 ); - - plot->setAxisScale( axisId, domainY1, domainY2 ); - } - } - plot->setAutoReplot( doReplot ); - plot->replot(); - } - } - - /* - QwtPlot* plt = plot(); - if ( !plt ) return; - - const QRectF& rect = m_data->zoomStack[m_data->zoomRectIndex]; - if ( rect != scaleRect() ) - { - const bool doReplot = plt->autoReplot(); - plt->setAutoReplot( false ); - - double x1 = rect.left(); - double x2 = rect.right(); - if ( !plt->axisScaleDiv( xAxis() ).isIncreasing() ) qSwap( x1, x2 ); - - plt->setAxisScale( xAxis(), x1, x2 ); - - double y1 = rect.top(); - double y2 = rect.bottom(); - if ( !plt->axisScaleDiv( yAxis() ).isIncreasing() ) qSwap( y1, y2 ); - - plt->setAxisScale( yAxis(), y1, y2 ); - - plt->setAutoReplot( doReplot ); - - plt->replot(); - } -*/ -} - -/*! - Reinitialize the axes, and set the zoom base to their scales. - */ - -void RiuQwtPlotZoomerMultiAxes::axesChanged() -{ - QwtPlotPicker::axesChanged(); - setZoomBase( scaleRect() ); -} - -/*! - Qt::MidButton zooms out one position on the zoom stack, - Qt::RightButton to the zoom base. - - Changes the current position on the stack, but doesn't pop - any rectangle. - - \note The mouse events can be changed, using - QwtEventPattern::setMousePattern: 2, 1 - */ -void RiuQwtPlotZoomerMultiAxes::widgetMouseReleaseEvent( QMouseEvent* me ) -{ - if ( mouseMatch( MouseSelect2, me ) ) - zoom( 0 ); - else if ( mouseMatch( MouseSelect3, me ) ) - zoom( -1 ); - else if ( mouseMatch( MouseSelect6, me ) ) - zoom( +1 ); - else - QwtPlotPicker::widgetMouseReleaseEvent( me ); -} - -/*! - Qt::Key_Plus zooms in, Qt::Key_Minus zooms out one position on the - zoom stack, Qt::Key_Escape zooms out to the zoom base. - - Changes the current position on the stack, but doesn't pop - any rectangle. - - \note The keys codes can be changed, using - QwtEventPattern::setKeyPattern: 3, 4, 5 - */ - -void RiuQwtPlotZoomerMultiAxes::widgetKeyPressEvent( QKeyEvent* ke ) -{ - if ( !isActive() ) - { - if ( keyMatch( KeyUndo, ke ) ) - zoom( -1 ); - else if ( keyMatch( KeyRedo, ke ) ) - zoom( +1 ); - else if ( keyMatch( KeyHome, ke ) ) - zoom( 0 ); - } - - QwtPlotPicker::widgetKeyPressEvent( ke ); -} - -/*! - Move the current zoom rectangle. - - \param dx X offset - \param dy Y offset - - \note The changed rectangle is limited by the zoom base - */ -void RiuQwtPlotZoomerMultiAxes::moveBy( double dx, double dy ) -{ - const QRectF& rect = m_data->zoomStack[m_data->zoomRectIndex]; - moveTo( QPointF( rect.left() + dx, rect.top() + dy ) ); -} - -/*! - Move the the current zoom rectangle. - - \param pos New position - - \sa QRectF::moveTo() - \note The changed rectangle is limited by the zoom base - */ -void RiuQwtPlotZoomerMultiAxes::moveTo( const QPointF& pos ) -{ - double x = pos.x(); - double y = pos.y(); - - if ( x < zoomBase().left() ) x = zoomBase().left(); - if ( x > zoomBase().right() - zoomRect().width() ) x = zoomBase().right() - zoomRect().width(); - - if ( y < zoomBase().top() ) y = zoomBase().top(); - if ( y > zoomBase().bottom() - zoomRect().height() ) y = zoomBase().bottom() - zoomRect().height(); - - if ( x != zoomRect().left() || y != zoomRect().top() ) - { - m_data->zoomStack[m_data->zoomRectIndex].moveTo( x, y ); - rescale(); - } -} - -/*! - \brief Check and correct a selected rectangle - - Reject rectangles with a height or width < 2, otherwise - expand the selected rectangle to a minimum size of 11x11 - and accept it. - - \return true If the rectangle is accepted, or has been changed - to an accepted one. - */ + if ( !plot ) return false; -bool RiuQwtPlotZoomerMultiAxes::accept( QPolygon& pa ) const -{ + const QPolygon& pa = selection(); if ( pa.count() < 2 ) return false; QRect rect = QRect( pa.first(), pa.last() ); rect = rect.normalized(); - const int minSize = 2; - if ( rect.width() < minSize && rect.height() < minSize ) return false; - - const int minZoomSize = 11; - - const QPoint center = rect.center(); - rect.setSize( rect.size().expandedTo( QSize( minZoomSize, minZoomSize ) ) ); - rect.moveCenter( center ); - - pa.resize( 2 ); - pa[0] = rect.topLeft(); - pa[1] = rect.bottomRight(); + zoomFromScreenCoords( rect ); return true; } -/*! - \brief Limit zooming by a minimum rectangle - - \return zoomBase().width() / 10e4, zoomBase().height() / 10e4 - */ -QSizeF RiuQwtPlotZoomerMultiAxes::minZoomSize() const +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RiuQwtPlotZoomerMultiAxes::zoomFromScreenCoords( const QRectF& screenCoords ) { - return QSizeF( m_data->zoomStack[0].width() / 10e4, m_data->zoomStack[0].height() / 10e4 ); -} - -/*! - Rejects selections, when the stack depth is too deep, or - the zoomed rectangle is minZoomSize(). + QwtPlot* plot = RiuQwtPlotZoomerMultiAxes::plot(); + if ( !plot ) return; - \sa minZoomSize(), maxStackDepth() - */ -void RiuQwtPlotZoomerMultiAxes::begin() -{ - if ( m_data->maxStackDepth >= 0 ) - { - if ( m_data->zoomRectIndex >= uint( m_data->maxStackDepth ) ) return; - } + const bool doReplot = plot->autoReplot(); + plot->setAutoReplot( false ); - const QSizeF minSize = minZoomSize(); - if ( minSize.isValid() ) + for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ ) { - const QSizeF sz = m_data->zoomStack[m_data->zoomRectIndex].size() * 0.9999; - - if ( minSize.width() >= sz.width() && minSize.height() >= sz.height() ) + const int axesCount = plot->axesCount( axisPos ); + for ( int i = 0; i < axesCount; i++ ) { - return; - } - } - - QwtPlotPicker::begin(); -} - -/*! - Expand the selected rectangle to minZoomSize() and zoom in - if accepted. + const QwtAxisId axisId( axisPos, i ); - \param ok If true, complete the selection and emit selected signals - otherwise discard the selection. - - \sa accept(), minZoomSize() - \return True if the selection has been accepted, false otherwise - */ -bool RiuQwtPlotZoomerMultiAxes::end( bool ok ) -{ - ok = QwtPlotPicker::end( ok ); - if ( !ok ) return false; + // Get the scale map for the axis used to convert between screen and domain coordinates + const QwtScaleMap map = plot->canvasMap( axisId ); - QwtPlot* plot = RiuQwtPlotZoomerMultiAxes::plot(); - if ( !plot ) return false; - - const QPolygon& pa = selection(); - if ( pa.count() < 2 ) return false; - - QRect rect = QRect( pa.first(), pa.last() ); - rect = rect.normalized(); - m_data->rectInScreenCoords = rect; - - const QwtScaleMap xMap = plot->canvasMap( xAxis() ); - const QwtScaleMap yMap = plot->canvasMap( yAxis() ); - - QRectF zoomRect = QwtScaleMap::invTransform( xMap, yMap, rect ).normalized(); + if ( axisId.isXAxis() ) + { + const double screenX1 = screenCoords.left(); + const double screenX2 = screenCoords.right(); + double domainX1 = map.invTransform( screenX1 ); + double domainX2 = map.invTransform( screenX2 ); + if ( !plot->axisScaleDiv( axisId ).isIncreasing() ) qSwap( domainX1, domainX2 ); - zoomRect = qwtExpandedZoomRect( zoomRect, minZoomSize(), xMap.transformation(), yMap.transformation() ); + plot->setAxisScale( axisId, domainX1, domainX2 ); + } + else + { + const double screenY1 = screenCoords.top(); + const double screenY2 = screenCoords.bottom(); + double domainY1 = map.invTransform( screenY1 ); + double domainY2 = map.invTransform( screenY2 ); + if ( plot->axisScaleDiv( axisId ).isIncreasing() ) qSwap( domainY1, domainY2 ); - zoom( zoomRect ); + plot->setAxisScale( axisId, domainY1, domainY2 ); + } + } - return true; + plot->setAutoReplot( doReplot ); + plot->replot(); + } } - -#if QWT_MOC_INCLUDE -#include "moc_qwt_plot_zoomer.cpp" -#endif diff --git a/ApplicationLibCode/UserInterface/RiuQwtPlotZoomerMultiAxes.h b/ApplicationLibCode/UserInterface/RiuQwtPlotZoomerMultiAxes.h index 0936724f65..8024e8ac19 100644 --- a/ApplicationLibCode/UserInterface/RiuQwtPlotZoomerMultiAxes.h +++ b/ApplicationLibCode/UserInterface/RiuQwtPlotZoomerMultiAxes.h @@ -1,141 +1,36 @@ -/****************************************************************************** - * Qwt Widget Library - * Copyright (C) 1997 Josef Wilgen - * Copyright (C) 2002 Uwe Rathmann - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the Qwt License, Version 1.0 - *****************************************************************************/ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023- Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight 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 General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once -#ifndef QWT_PLOT_ZOOMER_MULTI_AXES_H -#define QWT_PLOT_ZOOMER_MULTI_AXES_H - -#include "qwt_global.h" #include "qwt_plot_picker.h" -class QSizeF; -template -class QStack; - -/*! - \brief RiuQwtPlotZoomerMultiAxes provides stacked zooming for a plot widget - - RiuQwtPlotZoomerMultiAxes selects rectangles from user inputs ( mouse or keyboard ) - translates them into plot coordinates and adjusts the axes to them. - The selection is supported by a rubber band and optionally by displaying - the coordinates of the current mouse position. - - Zooming can be repeated as often as possible, limited only by - maxStackDepth() or minZoomSize(). Each rectangle is pushed on a stack. - - The default setting how to select rectangles is - a QwtPickerDragRectMachine with the following bindings: - - - QwtEventPattern::MouseSelect1\n - The first point of the zoom rectangle is selected by a mouse press, - the second point from the position, where the mouse is released. - - - QwtEventPattern::KeySelect1\n - The first key press selects the first, the second key press - selects the second point. - - - QwtEventPattern::KeyAbort\n - Discard the selection in the state, where the first point - is selected. - - To traverse the zoom stack the following bindings are used: - - - QwtEventPattern::MouseSelect3, QwtEventPattern::KeyUndo\n - Zoom out one position on the zoom stack - - - QwtEventPattern::MouseSelect6, QwtEventPattern::KeyRedo\n - Zoom in one position on the zoom stack - - - QwtEventPattern::MouseSelect2, QwtEventPattern::KeyHome\n - Zoom to the zoom base - - The setKeyPattern() and setMousePattern() functions can be used - to configure the zoomer actions. The following example - shows, how to configure the 'I' and 'O' keys for zooming in and out - one position on the zoom stack. The "Home" key is used to - "unzoom" the plot. - - \code - zoomer = new RiuQwtPlotZoomerMultiAxes( plot ); - zoomer->setKeyPattern( QwtEventPattern::KeyRedo, Qt::Key_I, Qt::ShiftModifier ); - zoomer->setKeyPattern( QwtEventPattern::KeyUndo, Qt::Key_O, Qt::ShiftModifier ); - zoomer->setKeyPattern( QwtEventPattern::KeyHome, Qt::Key_Home ); - \endcode - - RiuQwtPlotZoomerMultiAxes is tailored for plots with one x and y axis, but it is - allowed to attach a second RiuQwtPlotZoomerMultiAxes ( without rubber band and tracker ) - for the other axes. - - \note The realtime example includes an derived zoomer class that adds - scrollbars to the plot canvas. - - \sa QwtPlotPanner, QwtPlotMagnifier - */ - -class QWT_EXPORT RiuQwtPlotZoomerMultiAxes : public QwtPlotPicker +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class RiuQwtPlotZoomerMultiAxes : public QwtPlotPicker { - Q_OBJECT public: explicit RiuQwtPlotZoomerMultiAxes( QWidget*, bool doReplot = true ); - explicit RiuQwtPlotZoomerMultiAxes( QwtAxisId xAxis, QwtAxisId yAxis, QWidget*, bool doReplot = true ); - - virtual ~RiuQwtPlotZoomerMultiAxes(); - - virtual void setZoomBase( bool doReplot = true ); - virtual void setZoomBase( const QRectF& ); - - QRectF zoomBase() const; - QRectF zoomRect() const; - - void setMaxStackDepth( int ); - int maxStackDepth() const; - - const QStack& zoomStack() const; - void setZoomStack( const QStack&, int zoomRectIndex = -1 ); - - uint zoomRectIndex() const; - -public Q_SLOTS: - void moveBy( double dx, double dy ); - virtual void moveTo( const QPointF& ); - - virtual void zoom( const QRectF& ); - virtual void zoom( int offset ); - -Q_SIGNALS: - /*! - A signal emitting the zoomRect(), when the plot has been - zoomed in or out. - - \param rect Current zoom rectangle. - */ - - void zoomed( const QRectF& rect ); protected: - virtual void rescale(); - - virtual QSizeF minZoomSize() const; - - virtual void widgetMouseReleaseEvent( QMouseEvent* ) QWT_OVERRIDE; - virtual void widgetKeyPressEvent( QKeyEvent* ) QWT_OVERRIDE; - - virtual void begin() QWT_OVERRIDE; - virtual bool end( bool ok = true ) QWT_OVERRIDE; - virtual bool accept( QPolygon& ) const QWT_OVERRIDE; - - virtual void axesChanged() QWT_OVERRIDE; + bool end( bool ok = true ) override; private: - void init( bool doReplot ); - - class PrivateData; - PrivateData* m_data; + void zoomFromScreenCoords( const QRectF& screenCoords ); }; - -#endif