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/kugar/kudesigner_lib/view.cpp

842 lines
25 KiB

/* This file is part of the KDE project
Copyright (C) 2002-2004 Alexander Dymo <adymo@mksat.net>
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 "view.h"
#include <math.h>
#include <tqwmatrix.h>
#include <tqevent.h>
#include <tqpoint.h>
#include <tqcanvas.h>
#include <tqaction.h>
#include <tqcursor.h>
#include <tqpainter.h>
#include <tqbitmap.h>
#include <tqimage.h>
#include <tqprinter.h>
#include <kdebug.h>
#include <koproperty/property.h>
#include "canvas.h"
#include "box.h"
#include "commdefs.h"
#include "reportitem.h"
#include "label.h"
#include "field.h"
#include "specialfield.h"
#include "calcfield.h"
#include "line.h"
#include "kugartemplate.h"
#include "detailbase.h"
#include "band.h"
#include "command.h"
#include "plugin.h"
namespace Kudesigner
{
void SelectionRect::draw( TQPainter & painter )
{
// painter.setPen(TQt::NoPen);
/* TQPrinter pr;
if ( pr.setup() ) {
TQPainter p(&pr);
m_canvas->drawArea( m_canvas->rect(), &p );
} */
/* kdDebug(31000) << "creating pixmap" << endl;
TQPixmap mp(rect().size());
kdDebug(31000) << "creating painter" << endl;
TQPainter p(&mp);
kdDebug(31000) << "filling pixmap" << endl;
m_canvas->drawArea(m_canvas->rect(), &p);
kdDebug(31000) << "converting to image" << endl;
TQImage im = mp.convertToImage();
if (!im.isNull())
{
kdDebug(31000) << "do dither" << endl;
mp.convertFromImage(im, TQt::OrderedAlphaDither);
kdDebug(31000) << "creating brush" << endl;
TQBrush br(TDEGlobalSettings::highlightColor(),TQt::CustomPattern);
br.setPixmap(mp);
painter.setBrush(br);
}
kdDebug(31000) << "drawing" << endl;*/
// painter.drawRect(rect());
TQPen pen( TQColor( 0, 0, 0 ), 0, TQt::DotLine );
painter.setPen( pen );
painter.setBrush( TQBrush( NoBrush ) );
painter.drawRect( rect() );
// TQCanvasRectangle::draw(painter);
}
View::View( Canvas *canvas, TQWidget *parent, const char *name, WFlags f ) :
TQCanvasView( canvas, parent, name, f ), selectionBuf( 0 ), m_plugin( 0 ), m_canvas( canvas )
{
itemToInsert = 0;
moving = 0;
resizing = 0;
selectionStarted = 0;
request = RequestNone;
selectionRect = new SelectionRect( 0, 0, 0, 0, canvas );
connect( m_canvas, TQ_SIGNAL( itemSelected() ), this, TQ_SLOT( selectItem() ) );
}
void View::deleteItem( TQCanvasItemList &l )
{
for ( TQCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it )
{
m_canvas->unselectItem( static_cast<Kudesigner::Box*>( *it ) );
if ( m_canvas->kugarTemplate() ->removeReportItem( *it ) )
break;
}
}
void View::editItem( TQCanvasItemList & /* l */ )
{
//display editor for report items or sections
/* for (TQCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it)
{
if ((*it)->rtti() >= 1800) //for my own report items
{
CanvasKudesigner::Box *l = (CanvasKudesigner::Box*)(*it);
dlgItemOptions *dlgOpts = new dlgItemOptions(&(l->props), this);
dlgOpts->exec();
delete dlgOpts;
if ((*it)->rtti() == KugarTemplate)
((CanvasKugarTemplate*)(*it))->updatePaperProps();
(*it)->hide();
(*it)->show();
if ((*it)->rtti() < 2000)
((MyCanvas *)(m_canvas))->templ->arrangeSections();
m_canvas->update();
emit modificationPerformed();
break;
}
}*/
}
void View::selectItemFromList( TQCanvasItemList &l )
{
//display editor for report items or sections
for ( TQCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it )
{
if ( ( *it ) ->rtti() >= 1800 ) //include bands and the template itself
{
Kudesigner::Box * b = static_cast<Kudesigner::Box*>( *it );
if ( !m_canvas->selected.contains( b ) )
{
m_canvas->unselectAll();
m_canvas->selectItem( b, false );
m_canvas->update();
// tqWarning("selected item set");
// selected->drawHolders();
return ;
}
if ( m_canvas->selected.contains( b ) )
{
if ( m_canvas->selected.count() > 1 )
{
m_canvas->unselectAll();
m_canvas->selectItem( b, false );
m_canvas->update();
}
return ;
}
}
}
m_canvas->unselectAll();
// tqWarning("unselect");
}
void View::placeItem( TQCanvasItemList &l, TQMouseEvent *e )
{
for ( TQCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it )
{
if ( ( ( *it ) ->rtti() > 1800 ) && ( ( ( *it ) ->rtti() < 2000 ) ) )
{
int band = ( *it ) ->rtti();
int bandLevel = -1;
if ( ( band == Rtti_DetailHeader ) ||
( band == Rtti_Detail ) ||
( band == Rtti_DetailFooter ) )
bandLevel = static_cast<DetailBase*>( *it ) ->level();
emit itemPlaced( e->x(), e->y(), band, bandLevel );
// emit modificationPerformed();
}
}
itemToInsert = 0;
emit selectedActionProcessed();
}
bool View::startResizing( TQMouseEvent * /*e*/, TQPoint &p )
{
if ( m_canvas->selected.count() == 0 )
return false;
for ( BoxList::iterator it = m_canvas->selected.begin();
it != m_canvas->selected.end(); ++it )
{
Kudesigner::Box *cbx = *it;
resizing_type = cbx->isInHolder( p );
/* tqWarning("POINT: %d %d", p.x(), p.y());
tqWarning("RESIZE: %d", resizing_type);*/
if ( resizing_type )
{
m_canvas->selectItem( cbx, false );
//kdDebug()<<"A Widget should be resized"<<endl;
moving = 0;
resizing = cbx;
moving_start = p;
moving_offsetX = 0;
moving_offsetY = 0;
if ( cbx->rtti() > 2001 )
{
ReportItem * item = static_cast<ReportItem*>( cbx );
resizing_constraint.setX( ( int ) item->section() ->x() );
resizing_constraint.setY( ( int ) item->section() ->y() );
resizing_constraint.setWidth( item->section() ->width() );
resizing_constraint.setHeight(
item->section() ->height() );
if ( cbx->rtti() != Rtti_Line )
{
resizing_minSize.setWidth( 10 );
resizing_minSize.setHeight( 10 );
}
else
{
resizing_minSize.setWidth( 0 );
resizing_minSize.setHeight( 0 );
}
}
else
if ( cbx->rtti() >= Rtti_ReportHeader )
{
resizing_constraint = TQRect( 0, 0, 1000, 1000 );
resizing_minSize.setWidth( 0 );
resizing_minSize.setHeight( static_cast<Band*>( cbx ) ->minHeight() );
}
else
{
resizing_constraint = TQRect( 0, 0, 1000, 1000 );
resizing_minSize.setWidth( 0 );
resizing_minSize.setHeight( 10 );
}
return true;
}
}
return false;
}
void View::startMoveOrResizeOrSelectItem( TQCanvasItemList &l,
TQMouseEvent * /*e*/, TQPoint &p )
{
//allow user to move any item except for page rectangle
for ( TQCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it )
{
Kudesigner::Box *cb = static_cast<Kudesigner::Box*>( *it );
if ( cb->rtti() >= 1700 ) //> 2001)
{
moving_start = p;
moving_offsetX = 0;
moving_offsetY = 0;
resizing_type = cb->isInHolder( p );
if ( ( *it ) ->rtti() > 2001 )
{
ReportItem * item = static_cast<ReportItem*>( *it );
moving = item;
resizing = 0;
return ;
}
}
}
moving = 0;
resizing = 0;
// tqWarning("1");
selectionStarted = 1;
selectionRect->setX( p.x() );
selectionRect->setY( p.y() );
selectionRect->setZ( 50 );
// tqWarning("2");
selectionRect->show();
// tqWarning("3");
}
void View::contentsMousePressEvent( TQMouseEvent* e )
{
TQPoint p = inverseWorldMatrix().TQWMatrix::map( e->pos() );
TQCanvasItemList l = m_canvas->collisions( p );
//if there is a request for properties or for delete operation
//perform that and do not take care about mouse buttons
// tqWarning("mouse press");
switch ( request )
{
case RequestProps:
clearRequest();
editItem( l );
return ;
case RequestDelete:
deleteItem( l );
clearRequest();
return ;
case RequestNone:
break;
}
moving = 0;
resizing = 0;
selectionStarted = 0;
/* Kudesigner::Box *b;
tqWarning("Selected items:");
for (b = selected.first(); b; b = selected.next())
tqWarning("%s", b->props["Text"].first.latin1());
*/
switch ( e->button() )
{
case TQt::LeftButton:
if ( itemToInsert )
{
// tqWarning("placing item");
m_canvas->unselectAll();
placeItem( l, e );
}
else
{
// tqWarning("starting move or resize");
if ( !startResizing( e, p ) )
{
selectItemFromList( l );
startMoveOrResizeOrSelectItem( l, e, p );
}
}
break;
default:
break;
}
}
void View::contentsMouseReleaseEvent( TQMouseEvent* e )
{
selectionRect->setSize( 0, 0 );
selectionRect->setX( 0 );
selectionRect->setY( 0 );
selectionRect->hide();
TQPoint p = inverseWorldMatrix().TQWMatrix::map( e->pos() );
TQCanvasItemList l = m_canvas->collisions( p );
switch ( e->button() )
{
case TQt::LeftButton:
if ( selectionStarted )
finishSelection();
break;
/* case MidButton:
deleteItem(l);
break;
case RightButton:
editItem(l);
break;*/
default:
break;
}
}
void View::fixMinValues( double &pos, double minv, double &offset )
{
if ( pos < minv )
{
offset = offset + pos - minv;
pos = minv;
}
else
{
if ( offset < 0 )
{
offset = offset + pos - minv;
if ( offset < 0 )
pos = minv;
else
{
pos = offset + minv;
offset = 0;
}
}
}
}
void View::fixMaxValues( double &pos, double size, double maxv, double &offset )
{
double tmpMax = pos + size;
if ( tmpMax > maxv )
{
offset = offset + tmpMax - maxv;
pos = maxv - size;
}
else
{
if ( offset > 0 )
{
offset = offset + tmpMax - maxv;
if ( offset > 0 )
pos = maxv - size;
else
{
pos = offset + maxv - size;
offset = 0;
}
}
}
}
#ifdef TQ_WS_WIN
double rint( double x )
{
if ( fabs( x - floor( x ) ) < fabs( x - ceil( x ) ) )
return floor( x );
else
return ceil( x );
}
#endif
void View::stickToGrid( double &x, double &y )
{
int cx = int( rint( x / Config::gridSize() ) );
int cy = int( rint( y / Config::gridSize() ) );
x = cx * Config::gridSize();
y = cy * Config::gridSize();
}
void View::stickDimToGrid( double x, double y, double &w, double &h )
{
int rightX = int( x + w );
int bottomY = int( y + h );
int nx = int( rint( rightX /Config::gridSize() ) * Config::gridSize() );
int ny = int( rint( bottomY / Config::gridSize() ) * Config::gridSize() );
w = nx - x;
h = ny - y;
}
void View::contentsMouseMoveEvent( TQMouseEvent* e )
{
TQPoint p = inverseWorldMatrix().map( e->pos() );
/* TQCanvasItemList l=m_canvas->collisions(p);
setCursor(TQCursor(TQt::ArrowCursor));
unsetCursor();
for (TQCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it)
{
if ((*it)->rtti() > 2000)
{
CanvasReportItem *item = (CanvasReportItem*)(*it);
if (item->bottomRightResizableRect().contains(e->pos()))
setCursor(TQCursor(TQt::SizeFDiagCursor));
}
}*/
if ( moving )
{
double newXPos = moving->x() + p.x() - moving_start.x();
double newYPos = moving->y() + p.y() - moving_start.y();
fixMinValues( newYPos, moving->parentSection->y(), moving_offsetY );
fixMinValues( newXPos, moving->parentSection->x(), moving_offsetX );
fixMaxValues( newYPos, moving->height(), moving->parentSection->y() + moving->parentSection->height(), moving_offsetY );
fixMaxValues( newXPos, moving->width(), moving->parentSection->x() + moving->parentSection->width(), moving_offsetX );
double sx = newXPos;
double sy = newYPos;
if ( Config::gridSize() > 1 )
stickToGrid( newXPos, newYPos );
moving->move( newXPos, newYPos );
/* attempt to prevent item collisions
TQCanvasItemList l=m_canvas->collisions(moving->rect());
if (l.count() > 2)
{
moving->moveBy(-(p.x() - moving_start.x()),
-(p.y() - moving_start.y()));
m_canvas->update();
return;
}*/
// moving_start = p;
moving_start = TQPoint( p.x() + ( int ) ( newXPos - sx ), p.y() + ( int ) ( newYPos - sy ) );
moving->updateGeomProps();
m_canvas->update();
emit modificationPerformed();
}
if ( resizing )
{
TQCanvasRectangle * r = ( TQCanvasRectangle * ) resizing;
double newXPos = r->x();
double newYPos = r->y();
double h = r->height();
double w = r->width();
// kdDebug()<<"resizing"<<endl;
//vertical resizing
if ( resizing_type & Kudesigner::Box::ResizeBottom )
{
// kdDebug()<<"Resize bottom"<<endl;
h = h + p.y() - moving_start.y();
fixMaxValues( h, r->y(), resizing_constraint.bottom(), moving_offsetY );
if ( resizing->rtti() != Rtti_Line )
fixMinValues( h, resizing_minSize.height(), moving_offsetY );
}
else
if ( resizing_type & Kudesigner::Box::ResizeTop )
{
// kdDebug()<<"Resize top"<<endl;
newYPos = r->y() + p.y() - moving_start.y();
fixMinValues( newYPos, resizing_constraint.top(), moving_offsetY );
if ( resizing->rtti() != Rtti_Line )
fixMaxValues( newYPos, resizing_minSize.height(), r->y() + r->height(), moving_offsetY );
h = h + ( r->y() - newYPos );
}
//horizontal resizing
if ( resizing_type & Kudesigner::Box::ResizeRight )
{
//kdDebug()<<"Resize right"<<endl;
w = w + p.x() - moving_start.x();
fixMaxValues( w, r->x(), resizing_constraint.right(), moving_offsetX );
if ( resizing->rtti() != Rtti_Line )
fixMinValues( w, resizing_minSize.width(), moving_offsetX );
}
else
if ( resizing_type & Kudesigner::Box::ResizeLeft )
{
// kdDebug()<<"Resize left"<<endl;
newXPos = r->x() + p.x() - moving_start.x();
fixMinValues( newXPos, resizing_constraint.left(), moving_offsetX );
if ( resizing->rtti() != Rtti_Line )
fixMaxValues( newXPos, resizing_minSize.width(), r->x() + r->width(), moving_offsetX );
w = w + ( r->x() - newXPos );
}
//sticky stuff
double sx = newXPos;
double sy = newYPos;
if ( Config::gridSize() > 1 )
stickToGrid( newXPos, newYPos );
r->move( newXPos, newYPos );
int dx = ( int ) ( newXPos - sx );
int dy = ( int ) ( newYPos - sy );
// moving_start = TQPoint(p.x() + dx, p.y() + dy);
w -= dx;
h -= dy;
// moving_start = p;
double sw = w;
double sh = h;
stickDimToGrid( newXPos, newYPos, w, h );
int dw = ( int ) ( w - sw );
int dh = ( int ) ( h - sh );
moving_start = TQPoint( p.x() + dx + dw, p.y() + dy + dh );
r->setSize( ( int ) w, ( int ) h );
resizing->updateGeomProps();
m_canvas->update();
emit modificationPerformed();
}
if ( selectionStarted )
{
selectionRect->setSize( ( int ) ( e->pos().x() - selectionRect->x() ),
( int ) ( e->pos().y() - selectionRect->y() ) );
m_canvas->unselectAll();
TQCanvasItemList l = m_canvas->collisions( selectionRect->rect() );
for ( TQCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it )
{
TQRect r;
int left = selectionRect->rect().left();
int right = selectionRect->rect().right();
int top = selectionRect->rect().top();
int bottom = selectionRect->rect().bottom();
r.setLeft( left < right ? left : right );
r.setRight( left < right ? right : left );
r.setTop( top < bottom ? top : bottom );
r.setBottom( top < bottom ? bottom : top );
if ( ( ( *it ) ->rtti() > 2001 ) &&
( r.contains( static_cast<Kudesigner::Box*>( *it ) ->rect() ) ) )
{
m_canvas->selectItem( static_cast<Kudesigner::Box*>( *it ) );
m_canvas->update();
}
}
/* selectionRect->setSize(e->pos().x() - selectionRect->x(),
e->pos().y() - selectionRect->y());
unselectAll();
TQCanvasItemList l = m_canvas->collisions(selectionRect->rect());
for (TQCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it)
{
if ( ((*it)->rtti() > 2001) &&
(selectionRect->rect().contains(((CanvasKudesigner::Box*)(*it))->rect())) )
{
selectItem((CanvasKudesigner::Box*)(*it));
m_canvas->update();
}
}*/
}
}
void View::contentsMouseDoubleClickEvent( TQMouseEvent *e )
{
ReportItem * item = 0L;
if ( e->button() == TQt::LeftButton && m_canvas->selected.count() == 1 )
item = dynamic_cast<ReportItem*>( m_canvas->selected.first() );
if ( item )
{
item->fastProperty();
emit changed();
item->hide();
item->show();
}
}
void View::setRequest( RequestType r )
{
switch ( r )
{
case RequestProps:
TQApplication::restoreOverrideCursor();
TQApplication::setOverrideCursor( TQt::PointingHandCursor );
break;
case RequestDelete:
TQApplication::restoreOverrideCursor();
TQApplication::setOverrideCursor( TQt::ForbiddenCursor );
break;
case RequestNone:
TQApplication::restoreOverrideCursor();
break;
}
request = r;
}
void View::clearRequest()
{
TQApplication::restoreOverrideCursor();
request = RequestNone;
emit selectedEditActionProcessed();
}
bool View::requested()
{
if ( request == RequestNone )
return false;
else
return true;
}
void View::updateProperty()
{
for ( Kudesigner::BoxList::iterator it = m_canvas->selected.begin();
it != m_canvas->selected.end(); ++it )
{
Kudesigner::Box *b = *it;
// b->props[name]->setValue(value);
b->hide();
b->show();
if ( ( b->rtti() >= 1800 ) && ( b->rtti() < 2000 ) )
m_canvas->kugarTemplate() ->arrangeSections();
}
}
void View::finishSelection()
{
selectionStarted = false;
if ( !m_canvas->selected.isEmpty() )
{
Kudesigner::BoxList::const_iterator it = m_canvas->selected.begin();
Kudesigner::Box *b = *it;
Buffer *buf = new Buffer( &( b->props ) );
++it;
// tqWarning("== %d", m_canvas->selected.count());
// Kudesigner::BoxList::const_iterator it2 = m_canvas->selected.end();
// tqWarning("41: %d", it != it2);
for ( ; it != m_canvas->selected.end(); ++it )
{
b = *it;
buf->intersect( &( b->props ) );
}
emit selectionClear();
// delete selectionBuf;
selectionBuf = buf;
emit selectionMade( selectionBuf );
}
}
void View::setPlugin( KuDesignerPlugin *plugin )
{
m_plugin = plugin;
}
void View::contentsDragMoveEvent( TQDragMoveEvent * event )
{
//perhaps this could be optimized a little bit
if ( !m_plugin )
return ;
TQCanvasItemList l = m_canvas->collisions( event->pos() );
/* kdDebug()<<l.count()<<endl;*/
if ( l.count() < 2 )
{
event->ignore();
return ;
}
Kudesigner::Box *b = static_cast<Kudesigner::Box*>( *( l.begin() ) );
event->accept();
if ( m_plugin->dragMove( event, b ) )
event->accept();
else
event->ignore();
}
void View::contentsDragEnterEvent ( TQDragEnterEvent * /*event*/ )
{
// event->accept();
}
void View::keyPressEvent( TQKeyEvent *e )
{
kdDebug(31000) << k_funcinfo << endl;
if ( m_canvas->selected.count() == 1 )
{
ReportItem * item = static_cast<ReportItem *>( m_canvas->selected.first() );
switch ( e->key() )
{
case TQt::Key_Delete:
kdDebug(31000) << "Deleting selection" << endl;
/* unselectItem(item);
( (MyCanvas*) m_canvas )->templ->removeReportItem( item );
clearRequest();*/
// deleteSelected();
//FIXME: this disregards undo/redo
if ( m_canvas->selected.count() > 0 )
{
emit selectionClear();
DeleteReportItemsCommand *cmd = new DeleteReportItemsCommand( m_canvas,
m_canvas->selected );
cmd->execute();
delete cmd;
}
return ;
/* Adjust height with - and + */
case TQt::Key_Minus:
case TQt::Key_Plus:
{
int size = item->props[ "FontSize" ].value().toInt();
if ( e->key() == TQt::Key_Minus )
size--;
else
size++;
if ( size < 5 )
size = 5;
if ( size > 50 )
size = 50;
item->props[ "FontSize" ].setValue( size );
item->hide();
item->show();
return ;
}
default:
e->ignore();
}
}
}
void View::selectItem( )
{
if ( !selectionStarted )
finishSelection();
}
/*void View::deleteSelected( )
{
CanvasKudesigner::Box *b;
TQPtrList<CanvasKudesigner::Box> list = m_canvas->selected;
unselectAll();
for (b = list.first(); b; b = list.next())
{
( (MyCanvas*) m_canvas )->templ->removeReportItem( b );
}
}
*/
void View::setCanvas( Canvas *canvas )
{
if ( selectionRect )
delete selectionRect;
TQCanvasView::setCanvas( ( TQCanvas* ) canvas );
m_canvas = canvas;
selectionRect = new SelectionRect( 0, 0, 0, 0, m_canvas );
connect( m_canvas, TQ_SIGNAL( itemSelected() ), this, TQ_SLOT( selectItem() ) );
clearRequest();
}
void View::setGridSize( int size )
{
Config::setGridSize( size );
m_canvas->setChanged( m_canvas->rect() );
m_canvas->update();
}
}
#include "view.moc"