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() + 50) && 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.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Sep 28 04:04:01 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003