lib Library API Documentation

koRuler.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
00018 */
00019 
00020 // Description: Ruler (header)
00021 
00022 /******************************************************************/
00023 
00024 #include "koRuler.h"
00025 #include <klocale.h>
00026 #include <kdebug.h>
00027 #include <kiconloader.h>
00028 #include <qcursor.h>
00029 #include <qpainter.h>
00030 #include <qpopupmenu.h>
00031 #include <koUnit.h>
00032 
00033 class KoRulerPrivate {
00034 public:
00035     KoRulerPrivate() {
00036     }
00037     ~KoRulerPrivate() {}
00038 
00039     QWidget *canvas;
00040     int flags;
00041     int oldMx, oldMy;
00042     bool whileMovingBorderLeft, whileMovingBorderRight;
00043     bool whileMovingBorderTop, whileMovingBorderBottom;
00044     QPixmap pmFirst, pmLeft;
00045     KoTabChooser *tabChooser;
00046     KoTabulatorList tabList;
00047     // Do we have to remove a certain tab in the DC Event?
00048     KoTabulator removeTab;
00049     // The tab we're moving / clicking on - basically only valid between press and release time
00050     KoTabulator currTab;
00051     // The action we're currently doing - basically only valid between press and release time
00052     KoRuler::Action action;
00053     QPopupMenu *rb_menu;
00054     int mRemoveTab, mPageLayout; // menu item ids
00055     int frameEnd;
00056     double i_right;
00057     bool m_bReadWrite;
00058     bool doubleClickedIndent;
00059     bool rtl;
00060     bool mousePressed;
00061 };
00062 
00063 // Equality test for tab positions in particular
00064 static inline bool equals( double a, double b )  {
00065     return kAbs( a - b ) < 1E-4;
00066 }
00067 
00068 
00069 /******************************************************************/
00070 /* Class: KoRuler                                                 */
00071 /******************************************************************/
00072 
00073 const int KoRuler::F_TABS = 1;
00074 const int KoRuler::F_INDENTS = 2;
00075 const int KoRuler::F_HELPLINES = 4;
00076 const int KoRuler::F_NORESIZE = 8;
00077 
00078 /*================================================================*/
00079 KoRuler::KoRuler( QWidget *_parent, QWidget *_canvas, Orientation _orientation,
00080                  const KoPageLayout& _layout, int _flags, KoUnit::Unit _unit, KoTabChooser *_tabChooser )
00081     : QFrame( _parent ), buffer( width(), height() ), m_zoom(1.0), m_1_zoom(1.0),
00082       m_unit( _unit )
00083 {
00084     setWFlags( WResizeNoErase | WRepaintNoErase );
00085     setFrameStyle( Box | Raised );
00086 
00087     d=new KoRulerPrivate();
00088 
00089     d->tabChooser = _tabChooser;
00090 
00091     d->canvas = _canvas;
00092     orientation = _orientation;
00093     layout = _layout;
00094     d->flags = _flags;
00095 
00096     d->m_bReadWrite=true;
00097     d->doubleClickedIndent=false;
00098     diffx = 0;
00099     diffy = 0;
00100     i_left=0.0;
00101     i_first=0.0;
00102     d->i_right=0.0;
00103 
00104     setMouseTracking( true );
00105     d->mousePressed = false;
00106     d->action = A_NONE;
00107 
00108     d->oldMx = 0;
00109     d->oldMy = 0;
00110     d->rtl = false;
00111 
00112     showMPos = false;
00113     mposX = 0;
00114     mposY = 0;
00115     gridSize=0.0;
00116     hasToDelete = false;
00117     d->whileMovingBorderLeft = d->whileMovingBorderRight = d->whileMovingBorderTop = d->whileMovingBorderBottom = false;
00118 
00119     d->pmFirst = UserIcon( "koRulerFirst" );
00120     d->pmLeft = UserIcon( "koRulerLeft" );
00121     d->currTab.type = T_INVALID;
00122 
00123     d->removeTab.type = T_INVALID;
00124     if ( orientation == Qt::Horizontal ) {
00125         frameStart = qRound( zoomIt(layout.ptLeft) );
00126         d->frameEnd = qRound( zoomIt(layout.ptWidth - layout.ptRight) );
00127     } else {
00128         frameStart = qRound( zoomIt(layout.ptTop) );
00129         d->frameEnd = qRound( zoomIt(layout.ptHeight - layout.ptBottom) );
00130     }
00131     m_bFrameStartSet = false;
00132 
00133     setupMenu();
00134 
00135     // For compatibility, emitting doubleClicked shall emit openPageLayoutDia
00136     connect( this, SIGNAL( doubleClicked() ), this, SIGNAL( openPageLayoutDia() ) );
00137 }
00138 
00139 /*================================================================*/
00140 KoRuler::~KoRuler()
00141 {
00142     delete d->rb_menu;
00143     delete d;
00144 }
00145 
00146 void KoRuler::setPageLayoutMenuItemEnabled(bool b)
00147 {
00148     d->rb_menu->setItemEnabled(d->mPageLayout, b);
00149 }
00150 
00151 /*================================================================*/
00152 void KoRuler::setMousePos( int mx, int my )
00153 {
00154     if ( !showMPos || ( mx == mposX && my == mposY ) ) return;
00155 
00156     QPainter p( this );
00157     p.setRasterOp( Qt::NotROP );
00158 
00159     if ( orientation == Qt::Horizontal ) {
00160         if ( hasToDelete )
00161             p.drawLine( mposX, 1, mposX, height() - 1 );
00162         p.drawLine( mx, 1, mx, height() - 1 );
00163         hasToDelete = true;
00164     }
00165     else {
00166         if ( hasToDelete )
00167             p.drawLine( 1, mposY, width() - 1, mposY );
00168         p.drawLine( 1, my, width() - 1, my );
00169         hasToDelete = true;
00170     }
00171     p.end();
00172 
00173     mposX = mx;
00174     mposY = my;
00175 }
00176 
00177 // distance between the main lines (those with a number)
00178 double KoRuler::lineDistance() const
00179 {
00180     switch( m_unit ) {
00181     case KoUnit::U_INCH:
00182         return INCH_TO_POINT( m_zoom ); // every inch
00183     case KoUnit::U_PT:
00184         return 100.0 * m_zoom; // every 100 pt
00185     case KoUnit::U_MM:
00186     case KoUnit::U_CM:
00187     case KoUnit::U_DM:
00188         return CM_TO_POINT ( m_zoom ); // every cm
00189     case KoUnit::U_PI:
00190         return PI_TO_POINT ( 10.0 * m_zoom ); // every 10 pica
00191     case KoUnit::U_DD:
00192         return DD_TO_POINT( m_zoom ); // every diderot
00193     case KoUnit::U_CC:
00194         return CC_TO_POINT( 10.0 * m_zoom ); // every 10 cicero
00195     }
00196     // should never end up here
00197     return 100.0 * m_zoom;
00198 }
00199 
00200 /*================================================================*/
00201 void KoRuler::drawHorizontal( QPainter *_painter )
00202 {
00203     // Use a double-buffer pixmap
00204     QPainter p( &buffer );
00205     p.fillRect( 0, 0, width(), height(), QBrush( colorGroup().brush( QColorGroup::Background ) ) );
00206 
00207     int totalw = qRound( zoomIt(layout.ptWidth) );
00208     QString str;
00209     QFont font; // Use the global KDE font. Let's hope it's appropriate.
00210     font.setPixelSize( 8 );
00211     QFontMetrics fm( font );
00212 
00213     p.setBrush( colorGroup().brush( QColorGroup::Base ) );
00214 
00215     // Draw white rect
00216     QRect r;
00217     if ( !d->whileMovingBorderLeft )
00218         r.setLeft( -diffx + frameStart );
00219     else
00220         r.setLeft( d->oldMx );
00221     r.setTop( 0 );
00222     if ( !d->whileMovingBorderRight )
00223         r.setWidth(d->frameEnd-frameStart);
00224     else
00225         r.setRight( d->oldMx );
00226     r.setBottom( height() );
00227 
00228     p.drawRect( r );
00229     p.setFont( font );
00230 
00231     // Draw the numbers
00232     double dist = lineDistance();
00233     int maxwidth = 0;
00234     for ( double i = 0.0;i <= (double)totalw;i += dist ) {
00235         str = QString::number( KoUnit::ptToUnit( i / m_zoom, m_unit ) );
00236         int textwidth = fm.width( str );
00237         p.drawText( qRound(i) - diffx - qRound(textwidth * 0.5),
00238                     qRound(( height() - fm.height() ) * 0.5),
00239                     textwidth, height(), AlignLeft | AlignTop, str );
00240         maxwidth = QMAX( maxwidth, textwidth );
00241     }
00242 
00243     // Draw the medium-sized lines
00244     // Only if we have enough space (i.e. not at 33%)
00245     if ( dist > maxwidth + 1 )
00246     {
00247         for ( double i = dist * 0.5;i <= (double)totalw;i += dist ) {
00248             int ii=qRound(i);
00249             p.drawLine( ii - diffx, 5, ii - diffx, height() - 5 );
00250         }
00251     }
00252 
00253     // Draw the small lines
00254     // Only if we have enough space (i.e. not at 33%)
00255     if ( dist * 0.5 > maxwidth + 1 )
00256     {
00257         for ( double i = dist * 0.25;i <= (double)totalw;i += dist * 0.5 ) {
00258             int ii=qRound(i);
00259             p.drawLine( ii - diffx, 7, ii - diffx, height() - 7 );
00260         }
00261     }
00262 
00263     // Draw ending bar (at page width)
00264     int constant=zoomIt(1);
00265     p.drawLine( totalw - diffx + constant, 1, totalw - diffx + constant, height() - 1 );
00266     p.setPen( colorGroup().color( QColorGroup::Base ) );
00267     p.drawLine( totalw - diffx, 1, totalw - diffx, height() - 1 );
00268 
00269     // Draw starting bar (at 0)
00270     p.setPen( colorGroup().color( QColorGroup::Text ) );
00271     p.drawLine( -diffx, 1, -diffx, height() - 1 );
00272     p.setPen( colorGroup().color( QColorGroup::Base ) );
00273     p.drawLine( -diffx - constant, 1, -diffx - constant, height() - 1 );
00274 
00275     // Draw the indents triangles
00276     if ( d->flags & F_INDENTS ) {
00277         int top = 2;
00278         double halfPixmapWidth = d->pmFirst.width() * 0.5;
00279         // Cumulate i_first with correct indent
00280         double firstLineIdent = i_first + ( d->rtl ? d->i_right : i_left );
00281         p.drawPixmap( qRound( static_cast<double>(r.left()) + applyRtlAndZoom( firstLineIdent ) - halfPixmapWidth ),
00282                       top, d->pmFirst );
00283 
00284         int bottom = height() - d->pmLeft.height() - 2;
00285         halfPixmapWidth = d->pmLeft.width() * 0.5;
00286         p.drawPixmap( qRound( static_cast<double>(r.left()) + zoomIt(i_left) - halfPixmapWidth ),
00287                       bottom, d->pmLeft );
00288         p.drawPixmap( qRound( static_cast<double>(r.right()) - zoomIt(d->i_right) - halfPixmapWidth ),
00289                       bottom, d->pmLeft );
00290     }
00291 
00292     // Show the mouse position
00293     if ( d->action == A_NONE && showMPos ) {
00294         p.setPen( colorGroup().color( QColorGroup::Text ) );
00295         p.drawLine( mposX, 1, mposX, height() - 1 );
00296     }
00297     hasToDelete = false;
00298 
00299     // Draw the tabs
00300     if ( d->tabChooser && ( d->flags & F_TABS ) && !d->tabList.isEmpty() )
00301         drawTabs( p );
00302 
00303     p.end();
00304     _painter->drawPixmap( 0, 0, buffer );
00305 }
00306 
00307 /*================================================================*/
00308 void KoRuler::drawTabs( QPainter &_painter )
00309 {
00310     int ptPos = 0;
00311 
00312     _painter.setPen( QPen( colorGroup().color( QColorGroup::Text ), 2, SolidLine ) );
00313     // Check if we're in a mousemove event, removing a tab.
00314     // In that case, we'll have to skip drawing that one.
00315     bool willRemove = d->mousePressed && willRemoveTab( d->oldMy ) && d->currTab.type != T_INVALID;
00316 
00317     KoTabulatorList::ConstIterator it = d->tabList.begin();
00318     for ( ; it != d->tabList.end() ; it++ ) {
00319         if ( willRemove && equals( d->currTab.ptPos, (*it).ptPos ) )
00320             continue;
00321         ptPos = qRound(applyRtlAndZoom((*it).ptPos)) - diffx + frameStart;
00322         switch ( (*it).type ) {
00323         case T_LEFT: {
00324             ptPos -= 4;
00325             _painter.drawLine( ptPos + 4, height() - 4, ptPos + 20 - 4, height() - 4 );
00326             _painter.drawLine( ptPos + 5, 4, ptPos + 5, height() - 4 );
00327         } break;
00328         case T_CENTER: {
00329             ptPos -= 10;
00330             _painter.drawLine( ptPos + 4, height() - 4, ptPos + 20 - 4, height() - 4 );
00331             _painter.drawLine( ptPos + 20 / 2, 4, ptPos + 20 / 2, height() - 4 );
00332         } break;
00333         case T_RIGHT: {
00334             ptPos -= 16;
00335             _painter.drawLine( ptPos + 4, height() - 4, ptPos + 20 - 4, height() - 4 );
00336             _painter.drawLine( ptPos + 20 - 5, 4, ptPos + 20 - 5, height() - 4 );
00337         } break;
00338         case T_DEC_PNT: {
00339             ptPos -= 10;
00340             _painter.drawLine( ptPos + 4, height() - 4, ptPos + 20 - 4, height() - 4 );
00341             _painter.drawLine( ptPos + 20 / 2, 4, ptPos + 20 / 2, height() - 4 );
00342             _painter.fillRect( ptPos + 20 / 2 + 2, height() - 9, 3, 3,
00343                                colorGroup().color( QColorGroup::Text ) );
00344         } break;
00345         default: break;
00346         }
00347     }
00348 }
00349 
00350 /*================================================================*/
00351 void KoRuler::drawVertical( QPainter *_painter )
00352 {
00353     QPainter p( &buffer );
00354     p.fillRect( 0, 0, width(), height(), QBrush( colorGroup().brush( QColorGroup::Background ) ) );
00355 
00356     int totalh = qRound( zoomIt(layout.ptHeight) );
00357     // Clip rect - this gives basically always a rect like (2,2,width-2,height-2)
00358     QRect paintRect = _painter->clipRegion( QPainter::CoordPainter ).boundingRect();
00359     // Ruler rect
00360     QRect rulerRect( 0, -diffy, width(), totalh );
00361 
00362     if ( paintRect.intersects( rulerRect ) )  {
00363         QString str;
00364         QFont font; // Use the global KDE font. Let's hope it's appropriate.
00365         font.setPixelSize( 8 ); // Hardcode the size? (Werner)
00366         QFontMetrics fm( font );
00367 
00368         p.setBrush( colorGroup().brush( QColorGroup::Base ) );
00369 
00370         // Draw white rect
00371         QRect r;
00372         if ( !d->whileMovingBorderTop )
00373             r.setTop( -diffy + frameStart );
00374         else
00375             r.setTop( d->oldMy );
00376         r.setLeft( 0 );
00377         if ( !d->whileMovingBorderBottom )
00378             r.setHeight(d->frameEnd-frameStart);
00379         else
00380             r.setBottom( d->oldMy );
00381         r.setRight( width() );
00382 
00383         p.drawRect( r );
00384         p.setFont( font );
00385 
00386         // Draw the numbers
00387         double dist = lineDistance();
00388         int maxheight = 0;
00389         for ( double i = 0.0;i <= (double)totalh;i += dist ) {
00390             str = QString::number( KoUnit::ptToUnit( i / m_zoom, m_unit ) );
00391             int textheight = fm.height();
00392             maxheight = QMAX( maxheight, textheight );
00393             p.drawText( qRound(( width() - fm.width( str ) ) * 0.5),
00394                         qRound(i) - diffy - qRound(textheight * 0.5),
00395                         width(), textheight, AlignLeft | AlignTop, str );
00396         }
00397 
00398         // Draw the medium-sized lines
00399         if ( dist > maxheight + 1 )
00400         {
00401             for ( double i = dist * 0.5;i <= (double)totalh;i += dist ) {
00402                 int ii=qRound(i);
00403                 p.drawLine( 5, ii - diffy, width() - 5, ii - diffy );
00404             }
00405         }
00406 
00407         // Draw the small lines
00408         if ( dist * 0.5 > maxheight + 1 )
00409         {
00410             for ( double i = dist * 0.25;i <=(double)totalh;i += dist *0.5 ) {
00411                 int ii=qRound(i);
00412                 p.drawLine( 7, ii - diffy, width() - 7, ii - diffy );
00413             }
00414         }
00415 
00416         // Draw ending bar (at page height)
00417         p.drawLine( 1, totalh - diffy + 1, width() - 1, totalh - diffy + 1 );
00418         p.setPen( colorGroup().color( QColorGroup::Base ) );
00419         p.drawLine( 1, totalh - diffy, width() - 1, totalh - diffy );
00420 
00421         // Draw starting bar (at 0)
00422         p.setPen( colorGroup().color( QColorGroup::Text ) );
00423         p.drawLine( 1, -diffy, width() - 1, -diffy );
00424         p.setPen( colorGroup().color( QColorGroup::Base ) );
00425         p.drawLine( 1, -diffy - 1, width() - 1, -diffy - 1 );
00426     }
00427 
00428     // Show the mouse position
00429     if ( d->action == A_NONE && showMPos ) {
00430         p.setPen( colorGroup().color( QColorGroup::Text ) );
00431         p.drawLine( 1, mposY, width() - 1, mposY );
00432     }
00433     hasToDelete = false;
00434 
00435     p.end();
00436     _painter->drawPixmap( 0, 0, buffer );
00437 }
00438 
00439 void KoRuler::mousePressEvent( QMouseEvent *e )
00440 {
00441     if( !d->m_bReadWrite)
00442         return;
00443 
00444     d->oldMx = e->x();
00445     d->oldMy = e->y();
00446     d->mousePressed = true;
00447     d->removeTab.type = T_INVALID;
00448 
00449     switch ( e->button() ) {
00450     case RightButton:
00451         if(d->currTab.type == T_INVALID || !(d->flags & F_TABS))
00452             d->rb_menu->setItemEnabled(d->mRemoveTab, false);
00453         else
00454             d->rb_menu->setItemEnabled(d->mRemoveTab, true);
00455         d->rb_menu->popup( QCursor::pos() );
00456         d->action = A_NONE;
00457         d->mousePressed = false;
00458         return;
00459     case MidButton:
00460         // MMB shall do like double-click (it opens a dialog).
00461         handleDoubleClick();
00462         return;
00463     case LeftButton:
00464         if ( d->action == A_BR_RIGHT || d->action == A_BR_LEFT ) {
00465             if ( d->action == A_BR_RIGHT )
00466                 d->whileMovingBorderRight = true;
00467             else
00468                 d->whileMovingBorderLeft = true;
00469 
00470             if ( d->canvas )
00471                 drawLine(d->oldMx, -1);
00472             update();
00473         } else if ( d->action == A_BR_TOP || d->action == A_BR_BOTTOM ) {
00474             if ( d->action == A_BR_TOP )
00475                 d->whileMovingBorderTop = true;
00476             else
00477                 d->whileMovingBorderBottom = true;
00478 
00479             if ( d->canvas ) {
00480                 QPainter p( d->canvas );
00481                 p.setRasterOp( Qt::NotROP );
00482                 p.drawLine( 0, d->oldMy, d->canvas->width(), d->oldMy );
00483                 p.end();
00484             }
00485             update();
00486         } else if ( d->action == A_FIRST_INDENT || d->action == A_LEFT_INDENT || d->action == A_RIGHT_INDENT ) {
00487             if ( d->canvas )
00488                 drawLine(d->oldMx, -1);
00489         } else if ( d->action == A_TAB ) {
00490             if ( d->canvas && d->currTab.type != T_INVALID ) {
00491                 drawLine( qRound( applyRtlAndZoom(d->currTab.ptPos) ) + frameStart - diffx, -1 );
00492             }
00493         } else if ( d->tabChooser && ( d->flags & F_TABS ) && d->tabChooser->getCurrTabType() != 0 ) {
00494             int left = frameStart - diffx;
00495             int right = d->frameEnd - diffx;
00496 
00497             if( e->x()-left < 0 || right-e->x() < 0 )
00498                 return;
00499             KoTabulator tab;
00500             tab.filling = TF_BLANK;
00501             tab.ptWidth = 0.5;
00502             switch ( d->tabChooser->getCurrTabType() ) {
00503             case KoTabChooser::TAB_LEFT:
00504                 tab.type = T_LEFT;
00505                 break;
00506             case KoTabChooser::TAB_CENTER:
00507                 tab.type = T_CENTER;
00508                 break;
00509             case KoTabChooser::TAB_RIGHT:
00510                 tab.type = T_RIGHT;
00511                 break;
00512             case KoTabChooser::TAB_DEC_PNT:
00513                 tab.type = T_DEC_PNT;
00514                 tab.alignChar = KGlobal::locale()->decimalSymbol()[0];
00515                 break;
00516             default: break;
00517             }
00518             tab.ptPos = unZoomItRtl( e->x() + diffx - frameStart );
00519 
00520             KoTabulatorList::Iterator it=d->tabList.begin();
00521             while ( it!=d->tabList.end() && tab > (*it) )
00522         ++it;
00523 
00524             d->tabList.insert(it, tab);
00525 
00526             d->action = A_TAB;
00527             d->removeTab = tab;
00528             d->currTab = tab;
00529 
00530             emit tabListChanged( d->tabList );
00531             update();
00532         }
00533         else if ( d->flags & F_HELPLINES )
00534         {
00535         setCursor( orientation == Qt::Horizontal ?
00536                Qt::sizeVerCursor : Qt::sizeHorCursor );
00537             d->action = A_HELPLINES;
00538         }
00539     default:
00540         break;
00541     }
00542 }
00543 
00544 void KoRuler::mouseReleaseEvent( QMouseEvent *e )
00545 {
00546     d->mousePressed = false;
00547 
00548     // Hacky, but necessary to prevent multiple tabs with the same coordinates (Werner)
00549     bool fakeMovement=false;
00550     if(d->removeTab.type != T_INVALID) {
00551         mouseMoveEvent(e);
00552         fakeMovement=true;
00553     }
00554 
00555     if ( d->action == A_BR_RIGHT || d->action == A_BR_LEFT ) {
00556         d->whileMovingBorderRight = false;
00557         d->whileMovingBorderLeft = false;
00558 
00559         if ( d->canvas )
00560             drawLine(d->oldMx, -1);
00561         update();
00562         emit newPageLayout( layout );
00563     } else if ( d->action == A_BR_TOP || d->action == A_BR_BOTTOM ) {
00564         d->whileMovingBorderTop = false;
00565         d->whileMovingBorderBottom = false;
00566 
00567         if ( d->canvas ) {
00568             QPainter p( d->canvas );
00569             p.setRasterOp( Qt::NotROP );
00570             p.drawLine( 0, d->oldMy, d->canvas->width(), d->oldMy );
00571             p.end();
00572         }
00573         update();
00574         emit newPageLayout( layout );
00575     } else if ( d->action == A_FIRST_INDENT ) {
00576         if ( d->canvas )
00577             drawLine(d->oldMx, -1);
00578         update();
00579         emit newFirstIndent( i_first );
00580     } else if ( d->action == A_LEFT_INDENT ) {
00581         if ( d->canvas )
00582             drawLine(d->oldMx, -1);
00583         update();
00584         emit newLeftIndent( i_left );
00585     } else if ( d->action == A_RIGHT_INDENT ) {
00586         if ( d->canvas )
00587             drawLine(d->oldMx, -1);
00588         update();
00589         emit newRightIndent( d->i_right );
00590     } else if ( d->action == A_TAB ) {
00591         if ( d->canvas && !fakeMovement ) {
00592             drawLine( qRound( applyRtlAndZoom( d->currTab.ptPos ) ) + frameStart - diffx, -1);
00593         }
00594         if ( willRemoveTab( e->y() ) )
00595         {
00596             d->tabList.remove(d->currTab);
00597         }
00598         qHeapSort( d->tabList );
00599 
00600         // Delete the new tabulator if it is placed on top of another.
00601         KoTabulatorList::ConstIterator tmpTab=d->tabList.begin();
00602         int count=0;
00603         while(tmpTab!=d->tabList.end()) {
00604             if( equals( (*tmpTab).ptPos, d->currTab.ptPos ) ) {
00605                 count++;
00606                 if(count > 1) {
00607                     d->tabList.remove(d->currTab);
00608                     break;
00609                 }
00610             }
00611             tmpTab++;
00612         }
00613         //searchTab( e->x() ); // DF: why set currTab here?
00614         emit tabListChanged( d->tabList );
00615         update();
00616     }
00617     else if( d->action == A_HELPLINES )
00618     {
00619         emit addHelpline( e->pos(), orientation == Qt::Horizontal);
00620         setCursor( ArrowCursor );
00621     }
00622     d->currTab.type = T_INVALID; // added (DF)
00623 }
00624 
00625 void KoRuler::mouseMoveEvent( QMouseEvent *e )
00626 {
00627     hasToDelete = false;
00628 
00629     int pw = d->frameEnd - frameStart;
00630     int ph = qRound(zoomIt(layout.ptHeight));
00631     int left = frameStart - diffx;
00632     int top = qRound(zoomIt(layout.ptTop));
00633     top -= diffy;
00634     int right = d->frameEnd - diffx;
00635     int bottom = qRound(zoomIt(layout.ptBottom));
00636     bottom = ph - bottom - diffy;
00637     // Cumulate first-line-indent
00638     int ip_first = qRound( zoomIt( i_first + ( d->rtl ? d->i_right : i_left) ) );
00639     int ip_left = qRound(zoomIt(i_left));
00640     int ip_right = qRound(zoomIt(d->i_right));
00641 
00642     int mx = e->x();
00643     mx = mx+diffx < 0 ? 0 : mx;
00644     int my = e->y();
00645     my = my+diffy < 0 ? 0 : my;
00646 
00647     switch ( orientation ) {
00648         case Qt::Horizontal: {
00649             if ( !d->mousePressed ) {
00650                 setCursor( ArrowCursor );
00651                 d->action = A_NONE;
00653                 // At the moment, moving the left and right border indicators
00654                 // is disabled when setFrameStartEnd has been called (i.e. in KWord)
00655                 // Changing the layout margins directly from it would be utterly wrong
00656                 // (just try the 2-columns modes...). What needs to be done is:
00657                 // emitting a signal frameResized in mouseReleaseEvent, when a left/right
00658                 // border has been moved, and in kword we need to update the margins from
00659                 // there, if the left border of the 1st column or the right border of the
00660                 // last column was moved... and find what to do with the other borders.
00661                 // And for normal frames, resize the frame without touching the page layout.
00662                 // All that is too much for now -> disabling.
00663                 if ( !m_bFrameStartSet )
00664                 {
00665                     if ( mx > left - 5 && mx < left + 5 ) {
00666                         setCursor( Qt::sizeHorCursor );
00667                         d->action = A_BR_LEFT;
00668                     } else if ( mx > right - 5 && mx < right + 5 ) {
00669                         setCursor( Qt::sizeHorCursor );
00670                         d->action = A_BR_RIGHT;
00671                     }
00672                 }
00673                 if ( d->flags & F_INDENTS ) {
00674                     int firstX = d->rtl ? right - ip_first : left + ip_first;
00675                     if ( mx > firstX - 5 && mx < firstX + 5 &&
00676                          my >= 2 && my <= d->pmFirst.size().height() + 2 ) {
00677                         setCursor( ArrowCursor );
00678                         d->action = A_FIRST_INDENT;
00679                     } else if ( mx > left + ip_left - 5 && mx < left + ip_left + 5 &&
00680                                 my >= height() - d->pmLeft.size().height() - 2 && my <= height() - 2 ) {
00681                         setCursor( ArrowCursor );
00682                         d->action = A_LEFT_INDENT;
00683                     } else if ( mx > right - ip_right - 5 && mx < right - ip_right + 5 &&
00684                                 my >= height() - d->pmLeft.size().height() - 2 && my <= height() - 2 ) {
00685                         setCursor( ArrowCursor );
00686                         d->action = A_RIGHT_INDENT;
00687                     }
00688                 }
00689                 if ( d->flags & F_TABS )
00690                     searchTab(mx);
00691             } else {
00692                 // Calculate the new value.
00693                 int newPos=mx;
00694                 if( newPos!=right && gridSize!=0.0 && (e->state() & ShiftButton)==0) { // apply grid.
00695                     double grid=zoomIt(gridSize * 16);
00696                     newPos=qRound( ((newPos * 16 / grid) * grid) / 16 );
00697                 }
00698                 if(newPos-left < 0) newPos=left;
00699                 else if (right-newPos < 0) newPos=right;
00700                 double newValue = unZoomIt(static_cast<double>(newPos) - frameStart + diffx);
00701 
00702                 switch ( d->action ) {
00703                     case A_BR_LEFT: {
00704                         if ( d->canvas && mx < right-10 && mx+diffx-2 > 0) {
00705                             drawLine( d->oldMx, mx );
00706                             layout.ptLeft = unZoomIt(static_cast<double>(mx + diffx));
00707                             if( ip_left > right-left-15 ) {
00708                                 ip_left=right-left-15;
00709                                 ip_left=ip_left<0 ? 0 : ip_left;
00710                                 i_left=unZoomIt( ip_left );
00711                                 emit newLeftIndent( i_left );
00712                             }
00713                             if ( ip_right > right-left-15 ) {
00714                                 ip_right=right-left-15;
00715                                 ip_right=ip_right<0? 0 : ip_right;
00716                                 d->i_right=unZoomIt( ip_right );
00717                                 emit newRightIndent( d->i_right );
00718                             }
00719                             d->oldMx = mx;
00720                             d->oldMy = my;
00721                             update();
00722                         }
00723                         else
00724                             return;
00725                     } break;
00726                     case A_BR_RIGHT: {
00727                         if ( d->canvas && mx > left+10 && mx+diffx <= pw-2) {
00728                             drawLine( d->oldMx, mx );
00729                             layout.ptRight = unZoomIt(static_cast<double>(pw - ( mx + diffx )));
00730                             if( ip_left > right-left-15 ) {
00731                                 ip_left=right-left-15;
00732                                 ip_left=ip_left<0 ? 0 : ip_left;
00733                                 i_left=unZoomIt( ip_left );
00734                                 emit newLeftIndent( i_left );
00735                             }
00736                             if ( ip_right > right-left-15 ) {
00737                                 ip_right=right-left-15;
00738                                 ip_right=ip_right<0? 0 : ip_right;
00739                                 d->i_right=unZoomIt( ip_right );
00740                                 emit newRightIndent( d->i_right );
00741                             }
00742                             d->oldMx = mx;
00743                             d->oldMy = my;
00744                             update();
00745                         }
00746                         else
00747                             return;
00748                     } break;
00749                     case A_FIRST_INDENT: {
00750                         if ( d->canvas ) {
00751                             if (d->rtl)
00752                                 newValue = unZoomIt(pw) - newValue - d->i_right;
00753                             else
00754                                 newValue -= i_left;
00755                             if(newValue == i_first) break;
00756                             drawLine( d->oldMx, newPos);
00757                             d->oldMx=newPos;
00758                             i_first = newValue;
00759                             update();
00760                         }
00761                     } break;
00762                     case A_LEFT_INDENT: {
00763                         if ( d->canvas ) {
00764                             //if (d->rtl) newValue = unZoomIt(pw) - newValue;
00765                             if(newValue == i_left) break;
00766 
00767                             drawLine( d->oldMx, newPos);
00768                             i_left = newValue;
00769                             d->oldMx = newPos;
00770                             update();
00771                         }
00772                     } break;
00773                     case A_RIGHT_INDENT: {
00774                         if ( d->canvas ) {
00775                             double rightValue = unZoomIt(right - newPos);
00776                             //if (d->rtl) rightValue = unZoomIt(pw) - rightValue;
00777                             if(rightValue == d->i_right) break;
00778 
00779                             drawLine( d->oldMx, newPos);
00780                             d->i_right=rightValue;
00781                             d->oldMx = newPos;
00782                             update();
00783                         }
00784                     } break;
00785                     case A_TAB: {
00786                         if ( d->canvas) {
00787                             if (d->rtl) newValue = unZoomIt(pw) - newValue;
00788                             if(newValue == d->currTab.ptPos) break; // no change
00789                             QPainter p( d->canvas );
00790                             p.setRasterOp( Qt::NotROP );
00791                             // prevent 1st drawLine when we just created a new tab
00792                             // (it's a NOT line)
00793                             double pt;
00794                             int pt_fr;
00795                             if( d->currTab != d->removeTab )
00796                             {
00797                                 pt = applyRtlAndZoom(d->currTab.ptPos);
00798                                 pt_fr = qRound(pt) + frameStart - diffx;
00799                                 p.drawLine( pt_fr, 0, pt_fr, d->canvas->height() );
00800                             }
00801 
00802                             KoTabulatorList::Iterator it = d->tabList.find( d->currTab );
00803                             Q_ASSERT( it != d->tabList.end() );
00804                             if ( it != d->tabList.end() )
00805                                 (*it).ptPos = newValue;
00806                             d->currTab.ptPos = newValue;
00807 
00808                             pt = applyRtlAndZoom( newValue );
00809                             pt_fr = qRound(pt) + frameStart - diffx;
00810                             p.drawLine( pt_fr, 0, pt_fr, d->canvas->height() );
00811 
00812                             p.end();
00813                             d->oldMx = mx;
00814                             d->oldMy = my;
00815                             d->removeTab.type = T_INVALID;
00816                             update();
00817                         }
00818                     } break;
00819                     default: break;
00820                 }
00821             }
00822             if( d->action == A_HELPLINES )
00823             {
00824                 emit moveHelpLines( e->pos(), orientation == Qt::Horizontal);
00825             }
00826 
00827             return;
00828         } break;
00829         case Qt::Vertical: {
00830             if ( !d->mousePressed ) {
00831                 setCursor( ArrowCursor );
00832                 d->action = A_NONE;
00833                 if ( d->flags & F_NORESIZE )
00834                     break;
00835                 if ( my > top - 5 && my < top + 5 ) {
00836                     setCursor( Qt::sizeVerCursor );
00837                     d->action = A_BR_TOP;
00838                 } else if ( my > bottom - 5 && my < bottom + 5 ) {
00839                     setCursor( Qt::sizeVerCursor );
00840                     d->action = A_BR_BOTTOM;
00841                 }
00842             } else {
00843                 switch ( d->action ) {
00844                     case A_BR_TOP: {
00845                         if ( d->canvas && my < bottom-20 && my+diffy-2 > 0) {
00846                             QPainter p( d->canvas );
00847                             p.setRasterOp( Qt::NotROP );
00848                             p.drawLine( 0, d->oldMy, d->canvas->width(), d->oldMy );
00849                             p.drawLine( 0, my, d->canvas->width(), my );
00850                             p.end();
00851                             layout.ptTop = unZoomIt(static_cast<double>(my + diffy));
00852                             d->oldMx = mx;
00853                             d->oldMy = my;
00854                             update();
00855                         }
00856                         else
00857                             return;
00858                     } break;
00859                     case A_BR_BOTTOM: {
00860                         if ( d->canvas && my > top+20 && my+diffy < ph-2) {
00861                             QPainter p( d->canvas );
00862                             p.setRasterOp( Qt::NotROP );
00863                             p.drawLine( 0, d->oldMy, d->canvas->width(), d->oldMy );
00864                             p.drawLine( 0, my, d->canvas->width(), my );
00865                             p.end();
00866                             layout.ptBottom = unZoomIt(static_cast<double>(ph - ( my + diffy )));
00867                             d->oldMx = mx;
00868                             d->oldMy = my;
00869                             update();
00870                         }
00871                         else
00872                             return;
00873                     } break;
00874                     default: break;
00875                 }
00876             }
00877         } break;
00878     }
00879     if( d->action == A_HELPLINES )
00880     {
00881         emit moveHelpLines( e->pos(), orientation == Qt::Horizontal);
00882     }
00883 
00884     d->oldMx = mx;
00885     d->oldMy = my;
00886 }
00887 
00888 void KoRuler::resizeEvent( QResizeEvent *e )
00889 {
00890     QFrame::resizeEvent( e );
00891     buffer.resize( size() );
00892 }
00893 
00894 void KoRuler::mouseDoubleClickEvent( QMouseEvent* )
00895 {
00896     handleDoubleClick();
00897 }
00898 
00899 void KoRuler::handleDoubleClick()
00900 {
00901     if ( !d->m_bReadWrite )
00902         return;
00903 
00904     d->doubleClickedIndent = false;
00905     if ( d->tabChooser && ( d->flags & F_TABS ) ) {
00906         // Double-click and mousePressed inserted a tab -> need to remove it
00907         if ( d->tabChooser->getCurrTabType() != 0 && d->removeTab.type != T_INVALID && !d->tabList.isEmpty()) {
00908             uint c = d->tabList.count();
00909             d->tabList.remove( d->removeTab );
00910             Q_ASSERT( d->tabList.count() < c );
00911 
00912             d->removeTab.type = T_INVALID;
00913             d->currTab.type = T_INVALID;
00914             emit tabListChanged( d->tabList );
00915             setCursor( ArrowCursor );
00916             update();
00917             // --- we didn't click on a tab, fall out to indents test ---
00918         } else if ( d->action == A_TAB ) {
00919             // Double-click on a tab
00920             emit doubleClicked( d->currTab.ptPos ); // usually paragraph dialog
00921             return;
00922         }
00923     }
00924 
00925     // When Binary Compatibility is broken this will hopefully emit a
00926     // doubleClicked(int) to differentiate between double-clicking an
00927     // indent and double-clicking the ruler
00928     if ( d->flags & F_INDENTS ) {
00929         if ( d->action == A_LEFT_INDENT || d->action == A_RIGHT_INDENT || d->action == A_FIRST_INDENT ) {
00930             d->doubleClickedIndent = true;
00931             emit doubleClicked(); // usually paragraph dialog
00932             return;
00933         }
00934     }
00935 
00936     // Double-clicked nothing
00937     d->action = A_NONE;
00938     emit doubleClicked(); // usually page layout dialog
00939 }
00940 
00941 void KoRuler::setTabList( const KoTabulatorList & _tabList )
00942 {
00943     d->tabList = _tabList;
00944     qHeapSort(d->tabList);   // "Trust no one." as opposed to "In David we trust."
00945 
00946     // Note that d->currTab and d->removeTab could now point to
00947     // tabs which don't exist in d->tabList
00948 
00949     update();
00950 }
00951 
00952 double KoRuler::makeIntern( double _v )
00953 {
00954     return KoUnit::ptFromUnit( _v, m_unit );
00955 }
00956 
00957 void KoRuler::setupMenu()
00958 {
00959     d->rb_menu = new QPopupMenu();
00960     Q_CHECK_PTR( d->rb_menu );
00961     for ( uint i = 0 ; i <= KoUnit::U_LASTUNIT ; ++i )
00962     {
00963         KoUnit::Unit unit = static_cast<KoUnit::Unit>( i );
00964         d->rb_menu->insertItem( KoUnit::unitDescription( unit ), i /*as id*/ );
00965         if ( m_unit == unit )
00966             d->rb_menu->setItemChecked( i, true );
00967     }
00968     connect( d->rb_menu, SIGNAL( activated( int ) ), SLOT( slotMenuActivated( int ) ) );
00969 
00970     d->rb_menu->insertSeparator();
00971     d->mPageLayout=d->rb_menu->insertItem(i18n("Page Layout..."), this, SLOT(pageLayoutDia()));
00972     d->rb_menu->insertSeparator();
00973     d->mRemoveTab=d->rb_menu->insertItem(i18n("Remove Tabulator"), this, SLOT(rbRemoveTab()));
00974     d->rb_menu->setItemEnabled( d->mRemoveTab, false );
00975 }
00976 
00977 void KoRuler::uncheckMenu()
00978 {
00979     for ( uint i = 0 ; i <= KoUnit::U_LASTUNIT ; ++i )
00980         d->rb_menu->setItemChecked( i, false );
00981 }
00982 
00983 void KoRuler::setUnit( const QString& _unit )
00984 {
00985     setUnit( KoUnit::unit( _unit ) );
00986 }
00987 
00988 void KoRuler::setUnit( KoUnit::Unit unit )
00989 {
00990     m_unit = unit;
00991     uncheckMenu();
00992     d->rb_menu->setItemChecked( m_unit, true );
00993     update();
00994 }
00995 
00996 void KoRuler::setZoom( const double& zoom )
00997 {
00998     if(zoom==m_zoom)
00999         return;
01000     m_zoom=zoom;
01001     m_1_zoom=1/m_zoom;
01002     update();
01003 }
01004 
01005 bool KoRuler::willRemoveTab( int y ) const
01006 {
01007     return (y < -50 || y > height() + 25) && d->currTab.type != T_INVALID;
01008 }
01009 
01010 void KoRuler::rbRemoveTab() {
01011 
01012     d->tabList.remove( d->currTab );
01013     d->currTab.type = T_INVALID;
01014     emit tabListChanged( d->tabList );
01015     update();
01016 }
01017 
01018 void KoRuler::setReadWrite(bool _readWrite)
01019 {
01020     d->m_bReadWrite=_readWrite;
01021 }
01022 
01023 void KoRuler::searchTab(int mx) {
01024 
01025     int pos;
01026     d->currTab.type = T_INVALID;
01027     KoTabulatorList::ConstIterator it = d->tabList.begin();
01028     for ( ; it != d->tabList.end() ; ++it ) {
01029         pos = qRound(applyRtlAndZoom((*it).ptPos)) - diffx + frameStart;
01030         if ( mx > pos - 5 && mx < pos + 5 ) {
01031             setCursor( Qt::sizeHorCursor );
01032             d->action = A_TAB;
01033             d->currTab = *it;
01034             break;
01035         }
01036     }
01037 }
01038 
01039 void KoRuler::drawLine(int oldX, int newX) {
01040 
01041     QPainter p( d->canvas );
01042     p.setRasterOp( Qt::NotROP );
01043     p.drawLine( oldX, 0, oldX, d->canvas->height() );
01044     if(newX!=-1)
01045         p.drawLine( newX, 0, newX, d->canvas->height() );
01046     p.end();
01047 }
01048 
01049 void KoRuler::showMousePos( bool _showMPos )
01050 {
01051     showMPos = _showMPos;
01052     hasToDelete = false;
01053     mposX = -1;
01054     mposY = -1;
01055     update();
01056 }
01057 
01058 void KoRuler::setOffset( int _diffx, int _diffy )
01059 {
01060     //kdDebug() << "KoRuler::setOffset " << _diffx << "," << _diffy << endl;
01061     diffx = _diffx;
01062     diffy = _diffy;
01063     update();
01064 }
01065 
01066 void KoRuler::setFrameStartEnd( int _frameStart, int _frameEnd )
01067 {
01068     if ( _frameStart != frameStart || _frameEnd != d->frameEnd || !m_bFrameStartSet )
01069     {
01070         frameStart = _frameStart;
01071         d->frameEnd = _frameEnd;
01072         // Remember that setFrameStartEnd was called. This activates a slightly
01073         // different mode (when moving start and end positions).
01074         m_bFrameStartSet = true;
01075         update();
01076     }
01077 }
01078 
01079 void KoRuler::setRightIndent( double _right )
01080 {
01081     d->i_right = makeIntern( _right );
01082     update();
01083 }
01084 
01085 void KoRuler::setDirection( bool rtl )
01086 {
01087     d->rtl = rtl;
01088     update();
01089 }
01090 
01091 void KoRuler::changeFlags(int _flags)
01092 {
01093     d->flags = _flags;
01094 }
01095 
01096 int KoRuler::flags() const
01097 {
01098     return d->flags;
01099 }
01100 
01101 bool KoRuler::doubleClickedIndent() const
01102 {
01103     return d->doubleClickedIndent;
01104 }
01105 
01106 double KoRuler::applyRtlAndZoom( double value ) const
01107 {
01108     int frameWidth = d->frameEnd - frameStart;
01109     return d->rtl ? ( frameWidth - zoomIt( value ) ) : zoomIt( value );
01110 }
01111 
01112 double KoRuler::unZoomItRtl( int pixValue ) const
01113 {
01114     int frameWidth = d->frameEnd - frameStart;
01115     return d->rtl ? ( unZoomIt( (double)(frameWidth - pixValue) ) ) : unZoomIt( (double)pixValue );
01116 }
01117 
01118 void KoRuler::slotMenuActivated( int i )
01119 {
01120     if ( i >= 0 && i <= KoUnit::U_LASTUNIT )
01121     {
01122         KoUnit::Unit unit = static_cast<KoUnit::Unit>(i);
01123         setUnit( unit );
01124         emit unitChanged( KoUnit::unitName( unit ) );
01125     }
01126 }
01127 
01128 #include "koRuler.moc"
KDE Logo
This file is part of the documentation for lib Library Version 1.3.5.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Nov 17 13:19:25 2004 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2003