| # kdeui Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# kwordwrap.cpp

    00001 /* This file is part of the KDE libraries
    00002    Copyright (C) 2001 David Faure <david@mandrakesoft.com>
    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 version 2 as published by the Free Software Foundation.
    00007
    00008    This library is distributed in the hope that it will be useful,
    00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00011    Library General Public License for more details.
    00012
    00013    You should have received a copy of the GNU Library General Public License
    00014    along with this library; see the file COPYING.LIB.  If not, write to
    00015    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00016    Boston, MA 02111-1307, USA.
    00017 */
    00018
    00019 #include "kwordwrap.h"
    00020 #include <qpainter.h>
    00021
    00022 KWordWrap* KWordWrap::formatText( QFontMetrics &fm, const QRect & r, int /*flags*/, const QString & str, int len )
    00023 {
    00024     // The wordwrap algorithm
    00025     // The variable names and the global shape of the algorithm are inspired
    00026     // from QTextFormatterBreakWords::format().
    00027     //kdDebug() << "KWordWrap::formatText " << str << " r=" << r.x() << "," << r.y() << " " << r.width() << "x" << r.height() << endl;
    00028     KWordWrap* kw = new KWordWrap;
    00029     if ( len == -1 )
    00030         kw->m_text = str;
    00031     else
    00032         kw->m_text = str.left( len );
    00033     int height = fm.height();
    00034     if ( len == -1 )
    00035         len = str.length();
    00036     int lastBreak = -1;
    00037     int lineWidth = 0;
    00038     int x = 0;
    00039     int y = 0;
    00040     int w = r.width();
    00041     int textwidth = 0;
    00042     for ( int i = 0 ; i < len; ++i )
    00043     {
    00044         QChar c = str[i];
    00045         int ww = fm.charWidth( str, i );
    00046         // isBreakable is true when we can break _after_ this character.
    00047         bool isBreakable = ( c.isSpace() || c.isPunct() || c.isSymbol() )
    00048                            && ( c != '(' && c != '[' && c != '{' );
    00049         if ( !isBreakable && i < len-1 ) {
    00050             QChar nextc = str[i+1];
    00051             isBreakable = ( nextc == '(' || nextc == '[' || nextc == '{' );
    00052         }
    00053         /*kdDebug() << "c='" << QString(c) << "' i=" << i << "/" << len
    00054                   << " x=" << x << " ww=" << ww << " w=" << w
    00055                   << " lastBreak=" << lastBreak << " isBreakable=" << isBreakable << endl;*/
    00056         int breakAt = -1;
    00057         if ( x + ww > w && lastBreak != -1 ) // time to break and we know where
    00058             breakAt = lastBreak;
    00059         if ( x + ww > w - 4 && lastBreak == -1 ) // time to break but found nowhere [-> break here]
    00060             breakAt = i;
    00061         if ( i == len - 2 && x + ww + fm.charWidth( str, i+1 ) > w ) // don't leave the last char alone
    00062             breakAt = lastBreak == -1 ? i - 1 : lastBreak;
    00063         if ( breakAt != -1 )
    00064         {
    00065             //kdDebug() << "KWordWrap::formatText breaking after " << breakAt << endl;
    00066             kw->m_breakPositions.append( breakAt );
    00067             int thisLineWidth = lastBreak == -1 ? x + ww : lineWidth;
    00068             kw->m_lineWidths.append( thisLineWidth );
    00069             textwidth = QMAX( textwidth, thisLineWidth );
    00070             x = 0;
    00071             y += height;
    00072             if ( lastBreak != -1 )
    00073             {
    00074                 // Breakable char was found, restart from there
    00075                 i = lastBreak;
    00076                 lastBreak = -1;
    00077                 continue;
    00078             }
    00079         } else if ( isBreakable )
    00080         {
    00081             lastBreak = i;
    00082             lineWidth = x + ww;
    00083         }
    00084         x += ww;
    00085     }
    00086     textwidth = QMAX( textwidth, x );
    00087     kw->m_lineWidths.append( x );
    00088     y += height;
    00089     //kdDebug() << "KWordWrap::formatText boundingRect:" << r.x() << "," << r.y() << " " << textwidth << "x" << y << endl;
    00090     kw->m_boundingRect.setRect( 0, 0, textwidth, y );
    00091     return kw;
    00092 }
    00093
    00094 QString KWordWrap::wrappedString() const
    00095 {
    00096     // We use the calculated break positions to insert '\n' into the string
    00097     QString ws;
    00098     int start = 0;
    00099     QValueList<int>::ConstIterator it = m_breakPositions.begin();
    00100     for ( ; it != m_breakPositions.end() ; ++it )
    00101     {
    00102         int end = (*it);
    00103         ws += m_text.mid( start, end - start + 1 ) + '\n';
    00104         start = end + 1;
    00105     }
    00106     ws += m_text.mid( start );
    00107     return ws;
    00108 }
    00109
    00110 QString KWordWrap::truncatedString( bool dots ) const
    00111 {
    00112     QString ts;
    00113     QValueList<int>::ConstIterator it = m_breakPositions.begin();
    00114     if ( it != m_breakPositions.end() )
    00115     {
    00116         ts = m_text.left( (*it) + 1 );
    00117         if ( dots )
    00118             ts += "...";
    00119     }
    00120     else
    00121         ts = m_text;
    00122     return ts;
    00123 }
    00124
    00125 void KWordWrap::drawText( QPainter *painter, int textX, int textY, int flags ) const
    00126 {
    00127     //kdDebug() << "KWordWrap::drawText text=" << wrappedString() << " x=" << textX << " y=" << textY << endl;
    00128     // We use the calculated break positions to draw the text line by line using QPainter
    00129     int start = 0;
    00130     int y = 0;
    00131     QFontMetrics fm = painter->fontMetrics();
    00132     int height = fm.height(); // line height
    00133     int ascent = fm.ascent();
    00134     int maxwidth = m_boundingRect.width();
    00135     QValueList<int>::ConstIterator it = m_breakPositions.begin();
    00136     QValueList<int>::ConstIterator itw = m_lineWidths.begin();
    00137     for ( ; it != m_breakPositions.end() ; ++it, ++itw )
    00138     {
    00139         int end = (*it);
    00140         int x = textX;
    00141         if ( flags & Qt::AlignHCenter )
    00142             x += ( maxwidth - *itw ) / 2;
    00143         else if ( flags & Qt::AlignRight )
    00144             x += maxwidth - *itw;
    00145         painter->drawText( x, textY + y + ascent, m_text.mid( start, end - start + 1 ) );
    00146         y += height;
    00147         start = end + 1;
    00148     }
    00149     // Draw the last line
    00150     int x = textX;
    00151     if ( flags & Qt::AlignHCenter )
    00152         x += ( maxwidth - *itw ) / 2;
    00153     else if ( flags & Qt::AlignRight )
    00154         x += maxwidth - *itw;
    00155     painter->drawText( x, textY + y + ascent, m_text.mid( start ) );
    00156 }
    00157

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:57:59 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001