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.
kbarcode/kbarcode/mycanvasview.cpp

612 lines
18 KiB

/***************************************************************************
mycanvasview.cpp - description
-------------------
begin : Die Apr 23 2002
copyright : (C) 2002 by Dominik Seichter
email : domseichter@web.de
***************************************************************************/
/***************************************************************************
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "mycanvasview.h"
#include "commands.h"
#include "definition.h"
#include "measurements.h"
#include "kbarcodesettings.h"
// TQt includes
#include <tqcursor.h>
#include <tqpainter.h>
#include <tqpaintdevicemetrics.h>
// KDE includes
#include <kruler.h>
#include <kstatusbar.h>
MyCanvas::MyCanvas( TQObject* parent, const char* name )
: TQCanvas( parent, name )
{
m_grid = false;
setBackgroundColor( TQt::lightGray );
resize( 0, 0 );
}
MyCanvas::~MyCanvas()
{
}
void MyCanvas::drawBackground( TQPainter & painter, const TQRect & clip )
{
TQCanvas::drawBackground( painter, clip );
TQRect shadow1( int(m_rect.x() + m_rect.width()), m_rect.y() + 5, 5, m_rect.height() );
TQRect shadow2( m_rect.x()+ 5, int(m_rect.y() + m_rect.height()), m_rect.width(), 5 );
// draw background shadow
if( clip.intersects( shadow1 ) )
painter.fillRect( shadow1, TQt::black );
if( clip.intersects( shadow2 ) )
painter.fillRect( shadow2, TQt::black );
if( clip.intersects( m_rect ) ) {
painter.fillRect( m_rect, TQt::white );
if( m_grid ) {
painter.translate( m_rect.x(), m_rect.y() );
painter.setPen( TQPen( KBarcodeSettings::getInstance()->gridColor(), 0 ) );
for( int y = 0; y <= m_rect.height(); y += KBarcodeSettings::getInstance()->gridSize() )
for( int x = 0; x <= m_rect.width(); x += KBarcodeSettings::getInstance()->gridSize() )
painter.drawPoint( x, y );
painter.translate( -m_rect.x(), -m_rect.y() );
}
}
}
MyCanvasView::MyCanvasView( Definition* d, MyCanvas* c, TQWidget* parent, const char* name, WFlags f)
: TQCanvasView(c,parent,name,f)
{
statusbar = 0;
m_commov = 0;
canv = c;
rulerv = new KRuler( Qt::Vertical, this );
rulerh = new KRuler( Qt::Horizontal, this );
if( Measurements::measurementSystem() == Measurements::Metric ) {
rulerv->setRulerMetricStyle( KRuler::Millimetres );
rulerh->setRulerMetricStyle( KRuler::Millimetres );
} else {
rulerv->setRulerMetricStyle( KRuler::Inch );
rulerh->setRulerMetricStyle( KRuler::Inch );
}
rulerv->setMaxValue( 0 );
rulerh->setMaxValue( 0 );
viewport()->setMouseTracking( true );
setDefinition( d );
}
MyCanvasView::~MyCanvasView()
{
}
void MyCanvasView::snapPoint(TQPoint * point, TCanvasItem* item )
{
// move item to next grid position
// TODO: align the top left to the grid not the current mouse position!
/*
*/
if( item )
{
int difx = point->x() - (int)item->x();
int dify = point->y() - (int)item->y();
int x = (int)item->x();
int y = (int)item->y();
int grid = KBarcodeSettings::getInstance()->gridSize();
int modx = x % grid;
int mody = y % grid;
x -= modx;
y -= mody;
if(modx >= grid / 2)
x += grid;
if(mody >= grid / 2)
y += grid;
point->setX( x + difx );
point->setY( y + dify );
}
else
{
point->setX(point->x() - point->x() % KBarcodeSettings::getInstance()->gridSize());
point->setY(point->y() - point->y() % KBarcodeSettings::getInstance()->gridSize());
}
}
void MyCanvasView::contentsMouseMoveEvent(TQMouseEvent* e)
{
rulerh->slotNewValue( e->x() );
rulerv->slotNewValue( e->y() );
if( statusbar ) {
LabelUtils l;
int x = (int)l.pixelToMm( e->x(), TQT_TQPAINTDEVICE(this), LabelUtils::DpiX );
int y = (int)l.pixelToMm( e->y(), TQT_TQPAINTDEVICE(this), LabelUtils::DpiY );
statusbar->changeItem( i18n("Position: ") +
TQString( "%1%2 x %3%4" ).arg( x )
.arg( Measurements::system() ).arg( y ).arg( Measurements::system()), mouseid );
}
updateCursor( e->pos() );
// if no mouse button is pressed bail out now
if( !(e->state() & Qt::LeftButton ) ) {
(void)updateCursor( e->pos(), true );
return;
}
bool shift_pressed = e->state() & TQt::ShiftButton;
TCanvasItem* moving = getActive();
if( moving && !moving->item()->locked() ) {
TQPoint p = inverseWorldMatrix().map(e->pos());
if( m_mode == Barcode || m_mode == Inside ) {
TCanvasItemList list = getSelected();
for( unsigned int i = 0; i < list.count(); i++ ) {
TCanvasItem* moving = list[i];
TQPoint new_pt = TQPoint(p.x() - delta_pt.x(),p.y() - delta_pt.y());
if( canv->grid() ) {
snapPoint(&new_pt, moving) ;
}
LabelUtils l;
TQPoint pmm;
pmm.setX( (int)l.pixelToMm( new_pt.x() - getTranslation().x(), TQT_TQPAINTDEVICE(this), LabelUtils::DpiX ) * 1000 );
pmm.setY( (int)l.pixelToMm( new_pt.y() - getTranslation().y(), TQT_TQPAINTDEVICE(this), LabelUtils::DpiY ) * 1000 );
// Move the item
MoveCommand* mv = new MoveCommand( pmm.x() - moving->item()->rectMM().x(),
pmm.y() - moving->item()->rectMM().y(), moving );
mv->execute();
getMoveCommand()->addCommand( mv );
}
} else {
if( canv->grid() ) {
snapPoint(&p, NULL ) ;
}
LabelUtils l;
TQPoint pmm;
pmm.setX( (int)l.pixelToMm( p.x() - getTranslation().x(), TQT_TQPAINTDEVICE(this), LabelUtils::DpiX ) * 1000 );
pmm.setY( (int)l.pixelToMm( p.y() - getTranslation().y(), TQT_TQPAINTDEVICE(this), LabelUtils::DpiY ) * 1000 );
TQRect rmm = moving->item()->rectMM();
ResizeCommand* mv = new ResizeCommand( moving, shift_pressed );
switch( m_mode ) {
case RightMiddle:
mv->setRect( rmm.x(), rmm.y(), pmm.x() - rmm.x(), rmm.height() );
break;
case LeftMiddle:
mv->setRect( pmm.x(), rmm.y(), rmm.width()+ (rmm.x() - pmm.x()), rmm.height() );
break;
case BottomMiddle:
mv->setRect( rmm.x(), rmm.y(), rmm.width(), pmm.y() - rmm.y());
break;
case TopMiddle:
mv->setRect( rmm.x(), pmm.y(), rmm.width(), rmm.height()+ (rmm.y() - pmm.y()));
break;
case BottomLeft:
mv->setRect( pmm.x(), rmm.y(), rmm.width()+ (rmm.x() - pmm.x()), pmm.y() - rmm.y() );
break;
case BottomRight:
mv->setRect( rmm.x(), rmm.y(), pmm.x() - rmm.x(), pmm.y() - rmm.y() );
break;
case TopLeft:
mv->setRect( pmm.x(), pmm.y(), rmm.width()+ (rmm.x() - pmm.x()), rmm.height()+ (rmm.y() - pmm.y()));
break;
case TopRight:
mv->setRect( rmm.x(), pmm.y(), pmm.x() - rmm.x(),rmm.height()+ (rmm.y() - pmm.y()) );
break;
default:
break;
}
mv->execute();
getMoveCommand()->addCommand( mv );
}
moving_start = p;
emit movedSomething();
}
}
void MyCanvasView::contentsMousePressEvent(TQMouseEvent* e)
{
setActive( 0, e->state() & TQt::ControlButton );
TQCanvasItemList list = canvas()->allItems();
for( int z = MyCanvasView::getLowestZ( list ); z <= MyCanvasView::getHighestZ( list ); z++ )
for( unsigned int i = 0; i < list.count(); i++ )
if( list[i]->z() == z && isInside( e->pos(), list[i] ) )
setActive( list[i], (e->state() & TQt::ControlButton) );
if( getActive() ) {
moving_start = inverseWorldMatrix().map(e->pos());
m_mode = updateCursor( e->pos() );
old = getActive()->boundingRect();
delta_pt=TQPoint(e->x() - old.x(),e->y() - old.y());
}
if( e->button() == Qt::RightButton && getActive() )
emit showContextMenu( e->globalPos() );
}
void MyCanvasView::contentsMouseReleaseEvent(TQMouseEvent* e)
{
if( e->button() != Qt::LeftButton || getSelected().isEmpty() )
return;
if( m_commov ) {
history->addCommand( getMoveCommand(), false );
m_commov = 0;
}
updateCursor( e->pos() );
}
KMacroCommand* MyCanvasView::getMoveCommand()
{
if( !m_commov )
m_commov = new KMacroCommand( i18n("Item Moved") );
return m_commov;
}
void MyCanvasView::contentsMouseDoubleClickEvent(TQMouseEvent* e)
{
setActive( 0 );
TQCanvasItemList list = canvas()->allItems();
for( int z = MyCanvasView::getHighestZ( list ); z >= MyCanvasView::getLowestZ( list ); z-- )
for( unsigned int i = 0; i < list.count(); i++ )
if( list[i]->z() == z && isInside( e->pos(), list[i] ) ) {
setActive( list[i] );
emit doubleClickedItem( getActive() );
return;
}
}
bool MyCanvasView::isInside( TQPoint p, TQCanvasItem* item )
{
if( !item->isVisible() )
return false;
return item->boundingRect().contains( p );
}
int MyCanvasView::isEdge( TQPoint p, TQCanvasItem* item )
{
if( !isInside( p, item ) )
return Outside;
TQRect r = item->boundingRect();
int rh = r.y() + r.height();
int rw = r.x() + r.width();
if( p.x() > r.x() && p.x() < r.x() + SPOTSIZE ) {
// Left
if( p.y() > r.y() && p.y() < r.y() + SPOTSIZE )
return TopLeft;
if( p.y() > rh - SPOTSIZE && p.y() < rh )
return BottomLeft;
if( (r.height() - 2 * SPOTSIZE ) / 2 > SPOTSIZE ) {
// Middle
int start = ( r.y() + (r.height() - SPOTSIZE)/2 );
if( p.y() > start && p.y() < start + SPOTSIZE )
return LeftMiddle;
}
}
if( p.y() > r.y() && p.y() < r.y() + SPOTSIZE ) {
// Top
if( (r.width() - 2 * SPOTSIZE ) / 2 > SPOTSIZE ) {
// Middle
int start = ( r.x() + (r.width() - SPOTSIZE)/2 );
if( p.x() > start && p.x() < start + SPOTSIZE )
return TopMiddle;
}
}
if( p.y() > rh - SPOTSIZE && p.y() < rh ) {
// Bottom
if( (r.width() - 2 * SPOTSIZE ) / 2 > SPOTSIZE ) {
// Middle
int start = ( r.x() + (r.width() - SPOTSIZE)/2 );
if( p.x() > start && p.x() < start + SPOTSIZE )
return BottomMiddle;
}
}
if( p.x() > rw - SPOTSIZE && p.x() < rw ) {
// Right
if( p.y() > r.y() && p.y() < r.y() + SPOTSIZE )
return TopRight;
if( p.y() > rh - SPOTSIZE && p.y() < rh )
return BottomRight;
if( (r.height() - 2 * SPOTSIZE ) / 2 > SPOTSIZE ) {
// Middle
int start = ( r.y() + (r.height() - SPOTSIZE)/2 );
if( p.y() > start && p.y() < start + SPOTSIZE )
return RightMiddle;
}
}
return Inside;
}
void MyCanvasView::deleteCurrent()
{
TCanvasItemList list = getSelected();
if( !list.isEmpty() ) {
KMacroCommand* mc = new KMacroCommand( i18n("Delete") );
for( unsigned int i = 0; i < list.count(); i++ ) {
DeleteCommand* dc = new DeleteCommand( list[i] );
dc->execute();
mc->addCommand( dc );
}
history->addCommand( mc, false );
setActive( 0 );
canvas()->update();
}
}
void MyCanvasView::setCurrent( TQCanvasItem* item )
{
setSelected( item );
setActive( item );
}
void MyCanvasView::updateRuler()
{
rulerh->setGeometry( 20, 0, width() - 20, 20 );
rulerv->setGeometry( 0, 20, 20, height() - 20 );
if( def ) {
canv->setRect( TQRect( translation.x(), translation.y(), (int)def->getMeasurements().width( TQT_TQPAINTDEVICE(this) ), (int)def->getMeasurements().height( TQT_TQPAINTDEVICE(this) )) );
rulerv->setMaxValue( height() );
rulerh->setMaxValue( width() );
TQPaintDeviceMetrics pdm( this );
if( Measurements::measurementSystem() == Measurements::Metric ) {
rulerh->setPixelPerMark( (1/ 25.4)* pdm.logicalDpiX() );
rulerv->setPixelPerMark( (1/25.4)* pdm.logicalDpiY() );
}
}
}
void MyCanvasView::resizeEvent( TQResizeEvent * r )
{
setUpdatesEnabled( false );
TQPoint old = translation;
TQCanvasView::resizeEvent( r );
reposition();
updateRuler();
repaintContents();
old = translation - old;
TQCanvasItemList list = canvas()->allItems();
for( unsigned int i = 0; i < list.count(); i++ )
list[i]->moveBy( old.x(), old.y() );
setUpdatesEnabled( true );
}
void MyCanvasView::reposition()
{
/*
* it is difficult to handle the repositioning
* when a new scaling factor has been set.
* Therefore we divide by the old factor
* and multiply with the new one.
* As a result we have the correct width.
*/
int x = int((width() - (def->getMeasurements().width( TQT_TQPAINTDEVICE(this) )) ) / 2);
int y = int((height() - (def->getMeasurements().height( TQT_TQPAINTDEVICE(this) )) ) / 2);
// move label 30 pixels away from top/left if necessary
x = x > 0 ? x : 30;
y = y > 0 ? y : 30;
// make sure that there is some space around the label, therefore at 60 pixel
int w = ( this->width() - 2 > def->getMeasurements().width( TQT_TQPAINTDEVICE(this) ) ? this->width() - 2 : int(def->getMeasurements().width( TQT_TQPAINTDEVICE(this) ) + 60) );
int h = ( this->height() - 2 > def->getMeasurements().height( TQT_TQPAINTDEVICE(this) ) ? this->height() - 2 : int(def->getMeasurements().height( TQT_TQPAINTDEVICE(this) ) + 60) );
canvas()->resize( w, h );
translation = TQPoint( x, y );
}
void MyCanvasView::setDefinition( Definition* d )
{
def = d;
reposition();
updateRuler();
repaintContents( true );
}
void MyCanvasView::selectAll()
{
TQCanvasItemList list = canvas()->allItems();
for( unsigned int i = 0; i < list.count(); i++ )
setSelected( list[i], true );
}
void MyCanvasView::deSelectAll()
{
setSelected( 0 );
}
int MyCanvasView::getLowestZ( TQCanvasItemList list )
{
int v = 0;
for( unsigned int i = 0; i < list.count(); i++ )
if( list[i]->z() < v )
v = (int)list[i]->z();
return v;
}
int MyCanvasView::getHighestZ( TQCanvasItemList list )
{
int v = 0;
for( unsigned int i = 0; i < list.count(); i++ )
if( list[i]->z() > v )
v = (int)list[i]->z();
return v;
}
TCanvasItem* MyCanvasView::getActive()
{
TQCanvasItemList list = canvas()->allItems();
for( unsigned int i = 0; i < list.count(); i++ )
if( list[i]->isActive() )
return (TCanvasItem*)list[i];
return 0;
}
void MyCanvasView::setActive( TQCanvasItem* item, bool control )
{
emit selectionChanged();
TQCanvasItemList list = canvas()->allItems();
for( unsigned int i = 0; i < list.count(); i++ )
list[i]->setActive( false );
if( item )
item->setActive( true );
setSelected( item, control );
}
DocumentItemList MyCanvasView::getAllItems()
{
DocumentItemList l;
TQCanvasItemList list = canvas()->allItems();
for( unsigned int i = 0; i < list.count(); i++ )
l.append( ((TCanvasItem*)list[i])->item() );
return l;
}
TCanvasItemList MyCanvasView::getSelected()
{
TCanvasItemList l;
TQCanvasItemList list = canvas()->allItems();
for( unsigned int i = 0; i < list.count(); i++ )
if( list[i]->isSelected() )
l.append( (TCanvasItem*)list[i] );
return l;
}
void MyCanvasView::setSelected( TQCanvasItem* item, bool control )
{
if( !control ) {
TQCanvasItemList list = canvas()->allItems();
for( unsigned int i = 0; i < list.count(); i++ )
list[i]->setSelected( false );
}
if( item )
item->setSelected( true );
}
int MyCanvasView::updateCursor( TQPoint pos, bool pressed )
{
if( !getActive() ) {
this->setCursor( TQCursor::ArrowCursor );
return -1;
}
int mode = isEdge( pos, getActive() );
if( getActive()->item()->locked() )
{
pressed && mode != Outside ? setCursor( TQt::ForbiddenCursor ) : setCursor( TQCursor::ArrowCursor );
return mode;
}
if( getActive()->rtti() == eRtti_Barcode ) {
pressed && mode != Outside ? setCursor( TQCursor::SizeAllCursor ) : setCursor( TQCursor::ArrowCursor );
mode = Barcode;
return mode;
}
switch( mode ) {
case TopLeft:
case BottomRight:
this->setCursor( TQCursor::SizeFDiagCursor );
break;
case TopMiddle:
case BottomMiddle:
this->setCursor( TQCursor::SizeVerCursor );
break;
case TopRight:
case BottomLeft:
this->setCursor( TQCursor::SizeBDiagCursor );
break;
case RightMiddle:
case LeftMiddle:
this->setCursor( TQCursor::SizeHorCursor );
break;
case Inside:
pressed ? setCursor( TQCursor::SizeAllCursor ) : setCursor( TQCursor::ArrowCursor );
break;
case Outside:
default:
this->setCursor( TQCursor::ArrowCursor );
break;
};
return mode;
}
#include "mycanvasview.moc"