Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit 4d4dd68c authored by Peter Grasch's avatar Peter Grasch Committed by Albert Astals Cid

Fix usability issues with selecting annotations

REVIEW: 109627
parent e1595221
This diff is collapsed.
......@@ -93,6 +93,7 @@ class OKULAR_EXPORT Annotation
friend class AnnotationObjectRect;
friend class Document;
friend class DocumentPrivate;
friend class ObjectRect;
friend class Page;
friend class PagePrivate;
/// @endcond
......
......@@ -46,6 +46,13 @@ class AnnotationPrivate
virtual void setAnnotationProperties( const QDomNode& node );
virtual AnnotationPrivate* getNewAnnotationPrivate() = 0;
/**
* Determines the distance of the closest point of the annotation to the
* given point @p x @p y @p xScale @p yScale
* @since 0.17
*/
virtual double distanceSqr( double x, double y, double xScale, double yScale );
PagePrivate * m_page;
QString m_author;
......
......@@ -49,6 +49,72 @@ void NormalizedPoint::transform( const QTransform &matrix )
y = tmp_y;
}
double NormalizedPoint::distanceSqr( double x, double y, double xScale, double yScale ) const
{
return pow( (this->x - x) * xScale, 2 ) + pow( (this->y - y) * yScale, 2 );
}
/**
* Returns a vector from the given points @p a and @p b
* @internal
*/
NormalizedPoint operator-( const NormalizedPoint& a, const NormalizedPoint& b )
{
return NormalizedPoint( a.x - b.x, a.y - b.y );
}
/**
* @brief Calculates distance of the point @p x @p y @p xScale @p yScale to the line segment from @p start to @p end
*/
double NormalizedPoint::distanceSqr( double x, double y, double xScale, double yScale, const NormalizedPoint& start, const NormalizedPoint& end )
{
NormalizedPoint point( x, y );
double thisDistance;
NormalizedPoint lineSegment( end - start );
const double lengthSqr = pow( lineSegment.x, 2 ) + pow( lineSegment.y, 2 );
//if the length of the current segment is null, we can just
//measure the distance to either end point
if ( lengthSqr == 0.0 )
{
thisDistance = end.distanceSqr( x, y, xScale, yScale );
}
else
{
//vector from the start point of the current line segment to the measurement point
NormalizedPoint a = point - start;
//vector from the same start point to the end point of the current line segment
NormalizedPoint b = end - start;
//we're using a * b (dot product) := |a| * |b| * cos(phi) and the knowledge
//that cos(phi) is adjacent side / hypotenuse (hypotenuse = |b|)
//therefore, t becomes the length of the vector that represents the projection of
//the point p onto the current line segment
//(hint: if this is still unclear, draw it!)
float t = (a.x * b.x + a.y * b.y) / lengthSqr;
if ( t < 0 )
{
//projection falls outside the line segment on the side of "start"
thisDistance = point.distanceSqr( start.x, start.y, xScale, yScale );
}
else if ( t > 1 )
{
//projection falls outside the line segment on the side of the current point
thisDistance = point.distanceSqr( end.x, end.y, xScale, yScale );
}
else
{
//projection is within [start, *i];
//determine the length of the perpendicular distance from the projection to the actual point
NormalizedPoint direction = end - start;
NormalizedPoint projection = start - NormalizedPoint( -t * direction.x, -t * direction.y );
thisDistance = projection.distanceSqr( x, y, xScale, yScale );
}
}
return thisDistance;
}
QDebug operator<<( QDebug str, const Okular::NormalizedPoint& p )
{
str.nospace() << "NormPt(" << p.x << "," << p.y << ")";
......@@ -316,27 +382,29 @@ double ObjectRect::distanceSqr( double x, double y, double xScale, double yScale
{
case Action:
case Image:
{
const QRectF& rect( m_transformedPath.boundingRect() );
return NormalizedRect( rect.x(), rect.y(), rect.right(), rect.bottom() ).distanceSqr( x, y, xScale, yScale );
}
case OAnnotation:
{
const QPointF center = m_transformedPath.boundingRect().center();
return pow( ( x - center.x() ), 2 ) + pow( ( y - center.y() ) * xScale / yScale, 2 );
return static_cast<Annotation*>(m_object)->d_func()->distanceSqr( x, y, xScale, yScale );
}
case SourceRef:
{
const double ratio = yScale / xScale;
const SourceRefObjectRect * sr = static_cast< const SourceRefObjectRect * >( this );
const NormalizedPoint& point = sr->m_point;
if ( point.x == -1.0 )
{
return pow( ( y - point.y ) / ratio, 2 );
return pow( ( y - point.y ) * yScale, 2 );
}
else if ( point.y == -1.0 )
{
return pow( ( x - point.x ), 2 );
return pow( ( x - point.x ) * xScale, 2 );
}
else
{
return pow( ( x - point.x ), 2 ) + pow( ( y - point.y ) / ratio, 2 );
return pow( ( x - point.x ) * xScale, 2 ) + pow( ( y - point.y ) * yScale, 2 );
}
}
}
......
......@@ -15,6 +15,7 @@
#include <QtGui/QPainterPath>
#include <QtGui/QTransform>
#include <kdebug.h>
#include <math.h>
#include "global.h"
#include "okular_export.h"
......@@ -72,6 +73,19 @@ class OKULAR_EXPORT NormalizedPoint
*/
void transform( const QTransform &matrix );
/**
* Returns squared distance to point @p x @p y @p xScale @p yScale
* @since 0.17 (KDE 4.11)
*/
double distanceSqr( double x, double y, double xScale, double yScale ) const;
/**
* @brief Calculates distance of the point @p x @p y @p xScale @p yScale to the line segment from @p start to @p end
* @since 0.17 (KDE 4.11)
*/
static double distanceSqr( double x, double y, double xScale, double yScale, const NormalizedPoint& start, const NormalizedPoint& end );
/**
* The normalized x coordinate.
*/
......@@ -83,6 +97,7 @@ class OKULAR_EXPORT NormalizedPoint
double y;
};
/**
* NormalizedRect is a helper class which stores the coordinates
* of a normalized rect, which is a rectangle of @see NormalizedPoints.
......@@ -263,6 +278,27 @@ class OKULAR_EXPORT NormalizedRect
return right > pt.x;
}
/**
* Returns the distance of the point @p x @p y @p xScale @p yScale to the closest
* edge or 0 if the point is within the rectangle
* @since 0.17 (KDE 4.11)
*/
double distanceSqr(double x, double y, double xScale, double yScale) const
{
double distX = 0;
if ( x < left )
distX = left - x;
else if ( x > right )
distX = x - right;
double distY = 0;
if ( top > y )
distY = top - y;
else if (bottom < y)
distY = y - bottom;
return pow( distX * xScale, 2 ) + pow( distY * yScale, 2 );
}
/**
* The normalized left coordinate.
*/
......
......@@ -49,6 +49,8 @@
using namespace Okular;
static const double distanceConsideredEqual = 25; // 5px
static void deleteObjectRects( QLinkedList< ObjectRect * >& rects, const QSet<ObjectRect::ObjectType>& which )
{
QLinkedList< ObjectRect * >::iterator it = rects.begin(), end = rects.end();
......@@ -267,7 +269,7 @@ bool Page::hasObjectRect( double x, double y, double xScale, double yScale ) con
QLinkedList< ObjectRect * >::const_iterator it = m_rects.begin(), end = m_rects.end();
for ( ; it != end; ++it )
if ( (*it)->contains( x, y, xScale, yScale ) )
if ( (*it)->distanceSqr( x, y, xScale, yScale ) < distanceConsideredEqual )
return true;
return false;
......@@ -430,7 +432,7 @@ const ObjectRect * Page::objectRect( ObjectRect::ObjectType type, double x, doub
{
QLinkedList< ObjectRect * >::const_iterator it = m_rects.begin(), end = m_rects.end();
for ( ; it != end; ++it )
if ( ( (*it)->objectType() == type ) && (*it)->contains( x, y, xScale, yScale ) )
if ( ( (*it)->objectType() == type ) && (*it)->distanceSqr( x, y, xScale, yScale ) < distanceConsideredEqual )
return *it;
return 0;
}
......@@ -441,7 +443,7 @@ QLinkedList< const ObjectRect * > Page::objectRects( ObjectRect::ObjectType type
QLinkedList< ObjectRect * >::const_iterator it = m_rects.begin(), end = m_rects.end();
for ( ; it != end; ++it )
if ( ( (*it)->objectType() == type ) && (*it)->contains( x, y, xScale, yScale ) )
if ( ( (*it)->objectType() == type ) && (*it)->distanceSqr( x, y, xScale, yScale ) < distanceConsideredEqual )
result.append( *it );
return result;
......
......@@ -9,6 +9,9 @@ target_link_libraries( parttest ${KDE4_KDECORE_LIBS} ${KDE4_KPARTS_LIBS} ${QT_QT
kde4_add_unit_test( searchtest searchtest.cpp )
target_link_libraries( searchtest ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY} ${QT_QTTEST_LIBRARY} okularcore )
kde4_add_unit_test( annotationstest annotationstest.cpp )
target_link_libraries( annotationstest ${KDE4_KDECORE_LIBS} ${QT_QTGUI_LIBRARY} ${QT_QTTEST_LIBRARY} okularcore )
kde4_add_unit_test( urldetecttest urldetecttest.cpp )
target_link_libraries( urldetecttest ${KDE4_KDECORE_LIBS} ${QT_QTTEST_LIBRARY} )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment