You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/karbon/visitors/vselectobjects.cc

274 lines
6.3 KiB

/* This file is part of the KDE project
Copyright (C) 2002, The Karbon Developers
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., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "vselectobjects.h"
#include "vlayer.h"
#include "vdocument.h"
#include "vsegment.h"
#include <kdebug.h>
void
VSelectObjects::visitVPath( VPath& composite )
{
// Never select a deleted, locked or hidden object.
if( composite.state() > VObject::normal &&
composite.state() < VObject::selected )
return;
if( m_rectMode && m_rect.isEmpty() ) // in this mode everything is selected
{
visitVObject( composite );
return;
}
bool selected = false;
if( m_rectMode )
{
// Check if composite is completely inside the selection rectangle.
// This test should be the first test since it's the less expensive one.
if( m_rect.contains( composite.boundingBox() ) )
{
selected = true;
}
// Check if any of the rectangle corners is inside the composite.
// This test should be done before the intersect test since it covers many
// intersection cases.
if( !selected )
{
if(
composite.pointIsInside( m_rect.topLeft() ) ||
composite.pointIsInside( m_rect.topRight() ) ||
composite.pointIsInside( m_rect.bottomRight() ) ||
composite.pointIsInside( m_rect.bottomLeft() ) )
{
selected = true;
}
}
// Check if selection rectangle intersects the composite.
if( !selected )
{
// Path for holding a helper segment.
VSubpath path( 0L );
path.moveTo( m_rect.topLeft() );
path.lineTo( m_rect.topRight() );
if( composite.intersects( *path.getLast() ) )
{
selected = true;
}
else
{
path.getFirst()->setKnot( m_rect.bottomRight() );
if( composite.intersects( *path.getLast() ) )
{
selected = true;
}
else
{
path.getLast()->setKnot( m_rect.bottomLeft() );
if( composite.intersects( *path.getLast() ) )
{
selected = true;
}
else
{
path.getFirst()->setKnot( m_rect.topLeft() );
if( composite.intersects( *path.getLast() ) )
{
selected = true;
}
}
}
}
}
}
else
{
if( composite.pointIsInside( m_point ) )
selected = true;
}
if( selected )
{
if( m_select )
{
composite.setState( VObject::selected );
if( ! m_selection.containsRef( &composite ) )
m_selection.append( &composite );
}
else
{
composite.setState( VObject::normal );
m_selection.remove( &composite );
}
setSuccess();
}
}
void
VSelectObjects::visitVObject( VObject& object )
{
// Never select a deleted, locked or hidden object.
if( object.state() > VObject::normal &&
object.state() < VObject::selected )
return;
// selection by selection rectangle
if( m_rectMode )
{
if( !m_rect.isEmpty() )
{
if( m_select )
{
if( m_rect.intersects( object.boundingBox() ) )
{
object.setState( VObject::selected );
if( ! m_selection.containsRef( &object ) )
m_selection.append( &object );
setSuccess();
}
}
else
{
if( m_rect.intersects( object.boundingBox() ) )
{
object.setState( VObject::normal );
m_selection.remove( &object );
setSuccess();
}
}
}
else
{
if( m_select )
{
object.setState( VObject::selected );
if( ! m_selection.containsRef( &object ) )
m_selection.append( &object );
setSuccess();
}
else
{
object.setState( VObject::normal );
m_selection.remove( &object );
setSuccess();
}
}
}
// selection by point
else
{
if( object.boundingBox().contains( m_point ) )
{
if( m_select )
{
object.setState( VObject::selected );
if( ! m_selection.containsRef( &object ) )
m_selection.append( &object );
}
else
{
object.setState( VObject::normal );
m_selection.remove( &object );
}
setSuccess();
}
}
}
void
VSelectObjects::visitVLayer( VLayer& layer )
{
VDocument* doc = (VDocument*)layer.parent();
if ( ( layer.state() != VObject::deleted ) &&
( ( doc->selectionMode() == VDocument::AllLayers ) ||
( doc->selectionMode() == VDocument::VisibleLayers && ( layer.state() == VObject::normal || layer.state() == VObject::normal_locked ) ) ||
( doc->selectionMode() == VDocument::SelectedLayers && layer.selected() ) ||
( doc->selectionMode() == VDocument::ActiveLayer && doc->activeLayer() == &layer ) ) )
{
VObjectListIterator itr( layer.objects() );
for( ; itr.current(); ++itr )
itr.current()->accept( *this );
}
}
void
VSelectObjects::visitVText( VText& text )
{
// Never select a deleted, locked or hidden object.
if( text.state() > VObject::normal &&
text.state() < VObject::selected )
return;
int deselectedGlyphs = 0;
VPathListIterator itr( text.glyphs() );
for( ; itr.current(); ++itr )
{
VPath c( 0L );
c.combine( *itr.current() );
visitVPath( c );
if( m_select && c.state() == VObject::selected )
{
kdDebug(38000) << "selected: " << itr.current() << endl;
m_selection.remove( &c );
text.setState( VObject::selected );
if( ! m_selection.containsRef( &text ) )
m_selection.append( &text );
return;
}
else if( c.state() == VObject::normal )
{
kdDebug(38000) << "deselected: " << itr.current() << endl;
deselectedGlyphs++;
}
}
if( deselectedGlyphs >= 0 && uint( deselectedGlyphs ) == text.glyphs().count() )
{
text.setState( VObject::normal );
m_selection.remove( &text );
}
}
void
VSelectObjects::visitVGroup( VGroup& group )
{
// Never select a deleted, locked or hidden object.
if( group.state() > VObject::normal &&
group.state() < VObject::selected )
return;
if( ! m_insideGroups )
visitVObject( group );
else
{
VVisitor::visitVGroup( group );
}
}