• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeui
 

tdeui

  • tdeui
kwordwrap.cpp
1 /* This file is part of the KDE libraries
2  Copyright (C) 2001 David Faure <david@mandrakesoft.com>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License version 2 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Library General Public License for more details.
12 
13  You should have received a copy of the GNU Library General Public License
14  along with this library; see the file COPYING.LIB. If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  Boston, MA 02110-1301, USA.
17 */
18 
19 #include "kwordwrap.h"
20 #include <kdebug.h>
21 #include <kstringhandler.h>
22 #include <tqpainter.h>
23 
24 class KWordWrapPrivate {
25 public:
26  TQRect m_constrainingRect;
27 };
28 
29 KWordWrap::KWordWrap(const TQRect & r) {
30  d = new KWordWrapPrivate;
31  d->m_constrainingRect = r;
32 }
33 
34 KWordWrap* KWordWrap::formatText( TQFontMetrics &fm, const TQRect & r, int /*flags*/, const TQString & str, int len )
35 {
36  KWordWrap* kw = new KWordWrap( r );
37  // The wordwrap algorithm
38  // The variable names and the global shape of the algorithm are inspired
39  // from QTextFormatterBreakWords::format().
40  //kdDebug() << "KWordWrap::formatText " << str << " r=" << r.x() << "," << r.y() << " " << r.width() << "x" << r.height() << endl;
41  int height = fm.height();
42  if ( len == -1 )
43  kw->m_text = str;
44  else
45  kw->m_text = str.left( len );
46  if ( len == -1 )
47  len = str.length();
48  int lastBreak = -1;
49  int lineWidth = 0;
50  int x = 0;
51  int y = 0;
52  int w = r.width();
53  int textwidth = 0;
54  bool isBreakable = false;
55  bool wasBreakable = false; // value of isBreakable for last char (i-1)
56  bool isParens = false; // true if one of ({[
57  bool wasParens = false; // value of isParens for last char (i-1)
58 
59  for ( int i = 0 ; i < len; ++i )
60  {
61  TQChar c = str[i];
62  int ww = fm.charWidth( str, i );
63 
64  isParens = ( c == '(' || c == '[' || c == '{' );
65  // isBreakable is true when we can break _after_ this character.
66  isBreakable = ( c.isSpace() || c.isPunct() || c.isSymbol() ) & !isParens;
67 
68  // Special case for '(', '[' and '{': we want to break before them
69  if ( !isBreakable && i < len-1 ) {
70  TQChar nextc = str[i+1]; // look at next char
71  isBreakable = ( nextc == '(' || nextc == '[' || nextc == '{' );
72  }
73  // Special case for '/': after normal chars it's breakable (e.g. inside a path),
74  // but after another breakable char it's not (e.g. "mounted at /foo")
75  // Same thing after a parenthesis (e.g. "dfaure [/fool]")
76  if ( c == '/' && (wasBreakable || wasParens) )
77  isBreakable = false;
78 
79  /*kdDebug() << "c='" << TQString(c) << "' i=" << i << "/" << len
80  << " x=" << x << " ww=" << ww << " w=" << w
81  << " lastBreak=" << lastBreak << " isBreakable=" << isBreakable << endl;*/
82  int breakAt = -1;
83  if ( x + ww > w && lastBreak != -1 ) // time to break and we know where
84  breakAt = lastBreak;
85  if ( x + ww > w - 4 && lastBreak == -1 ) // time to break but found nowhere [-> break here]
86  breakAt = i;
87  if ( i == len - 2 && x + ww + fm.charWidth( str, i+1 ) > w ) // don't leave the last char alone
88  breakAt = lastBreak == -1 ? i - 1 : lastBreak;
89  if ( c == '\n' ) // Forced break here
90  {
91  if ( breakAt == -1 && lastBreak != -1) // only break if not already breaking
92  {
93  breakAt = i - 1;
94  lastBreak = -1;
95  }
96  // remove the line feed from the string
97  kw->m_text.remove(i, 1);
98  len--;
99  }
100  if ( breakAt != -1 )
101  {
102  //kdDebug() << "KWordWrap::formatText breaking after " << breakAt << endl;
103  kw->m_breakPositions.append( breakAt );
104  int thisLineWidth = lastBreak == -1 ? x + ww : lineWidth;
105  kw->m_lineWidths.append( thisLineWidth );
106  textwidth = TQMAX( textwidth, thisLineWidth );
107  x = 0;
108  y += height;
109  wasBreakable = true;
110  wasParens = false;
111  if ( lastBreak != -1 )
112  {
113  // Breakable char was found, restart from there
114  i = lastBreak;
115  lastBreak = -1;
116  continue;
117  }
118  } else if ( isBreakable )
119  {
120  lastBreak = i;
121  lineWidth = x + ww;
122  }
123  x += ww;
124  wasBreakable = isBreakable;
125  wasParens = isParens;
126  }
127  textwidth = TQMAX( textwidth, x );
128  kw->m_lineWidths.append( x );
129  y += height;
130  //kdDebug() << "KWordWrap::formatText boundingRect:" << r.x() << "," << r.y() << " " << textwidth << "x" << y << endl;
131  if ( r.height() >= 0 && y > r.height() )
132  textwidth = r.width();
133  int realY = y;
134  if ( r.height() >= 0 )
135  {
136  while ( realY > r.height() )
137  realY -= height;
138  realY = TQMAX( realY, 0 );
139  }
140  kw->m_boundingRect.setRect( 0, 0, textwidth, realY );
141  return kw;
142 }
143 
144 KWordWrap::~KWordWrap() {
145  delete d;
146 }
147 
148 TQString KWordWrap::wrappedString() const
149 {
150  // We use the calculated break positions to insert '\n' into the string
151  TQString ws;
152  int start = 0;
153  TQValueList<int>::ConstIterator it = m_breakPositions.begin();
154  for ( ; it != m_breakPositions.end() ; ++it )
155  {
156  int end = (*it);
157  ws += m_text.mid( start, end - start + 1 ) + '\n';
158  start = end + 1;
159  }
160  ws += m_text.mid( start );
161  return ws;
162 }
163 
164 TQString KWordWrap::truncatedString( bool dots ) const
165 {
166  if ( m_breakPositions.isEmpty() )
167  return m_text;
168 
169  TQString ts = m_text.left( m_breakPositions.first() + 1 );
170  if ( dots )
171  ts += "...";
172  return ts;
173 }
174 
175 static TQColor mixColors(double p1, TQColor c1, TQColor c2) {
176  return TQColor(int(c1.red() * p1 + c2.red() * (1.0-p1)),
177  int(c1.green() * p1 + c2.green() * (1.0-p1)),
178  int(c1.blue() * p1 + c2.blue() * (1.0-p1)));
179 }
180 
181 void KWordWrap::drawFadeoutText(TQPainter *p, int x, int y, int maxW,
182  const TQString &t) {
183  TQFontMetrics fm = p->fontMetrics();
184  TQColor bgColor = p->backgroundColor();
185  TQColor textColor = p->pen().color();
186 
187  if ( ( fm.boundingRect( t ).width() > maxW ) && ( t.length() > 1 ) ) {
188  unsigned int tl = 0;
189  int w = 0;
190  while ( tl < t.length() ) {
191  w += fm.charWidth( t, tl );
192  if ( w >= maxW )
193  break;
194  tl++;
195  }
196 
197  if (tl > 3) {
198  p->drawText( x, y, t.left( tl - 3 ) );
199  x += fm.width( t.left( tl - 3 ) );
200  }
201  int n = TQMIN( tl, 3);
202  for (int i = 0; i < n; i++) {
203  p->setPen( mixColors( 0.70 - i * 0.25, textColor, bgColor ) );
204  TQString s( t.at( tl - n + i ) );
205  p->drawText( x, y, s );
206  x += fm.width( s );
207  }
208  }
209  else
210  p->drawText( x, y, t );
211 }
212 
213 void KWordWrap::drawTruncateText(TQPainter *p, int x, int y, int maxW,
214  const TQString &t) {
215  TQString tmpText = KStringHandler::rPixelSqueeze( t, p->fontMetrics(), maxW );
216  p->drawText( x, y, tmpText, maxW );
217 }
218 
219 void KWordWrap::drawText( TQPainter *painter, int textX, int textY, int flags ) const
220 {
221  //kdDebug() << "KWordWrap::drawText text=" << wrappedString() << " x=" << textX << " y=" << textY << endl;
222  // We use the calculated break positions to draw the text line by line using QPainter
223  int start = 0;
224  int y = 0;
225  TQFontMetrics fm = painter->fontMetrics();
226  int height = fm.height(); // line height
227  int ascent = fm.ascent();
228  int maxwidth = m_boundingRect.width();
229  TQValueList<int>::ConstIterator it = m_breakPositions.begin();
230  TQValueList<int>::ConstIterator itw = m_lineWidths.begin();
231  for ( ; it != m_breakPositions.end() ; ++it, ++itw )
232  {
233  // if this is the last line, leave the loop
234  if ( (d->m_constrainingRect.height() >= 0) &&
235  ((y + 2 * height) > d->m_constrainingRect.height()) )
236  break;
237  int end = (*it);
238  int x = textX;
239  if ( flags & TQt::AlignHCenter )
240  x += ( maxwidth - *itw ) / 2;
241  else if ( flags & TQt::AlignRight )
242  x += maxwidth - *itw;
243  painter->drawText( x, textY + y + ascent, m_text.mid( start, end - start + 1 ) );
244  y += height;
245  start = end + 1;
246  }
247  // Draw the last line
248  int x = textX;
249  if ( flags & TQt::AlignHCenter )
250  x += ( maxwidth - *itw ) / 2;
251  else if ( flags & TQt::AlignRight )
252  x += maxwidth - *itw;
253  if ( (d->m_constrainingRect.height() < 0) ||
254  ((y + height) <= d->m_constrainingRect.height()) ) {
255  if ( it == m_breakPositions.end() )
256  painter->drawText( x, textY + y + ascent, m_text.mid( start ) );
257  else if (flags & FadeOut)
258  drawFadeoutText( painter, textX, textY + y + ascent,
259  d->m_constrainingRect.width(),
260  m_text.mid( start ) );
261  else if (flags & Truncate)
262  drawTruncateText( painter, textX, textY + y + ascent,
263  d->m_constrainingRect.width(),
264  m_text.mid( start ) );
265  else
266  painter->drawText( x, textY + y + ascent,
267  m_text.mid( start, (*it) - start + 1 ) );
268  }
269 }
KStringHandler::rPixelSqueeze
static TQString rPixelSqueeze(const TQString &name, const TQFontMetrics &fontMetrics, uint maxPixels)
KWordWrap
Word-wrap algorithm that takes into account beautifulness ;)
Definition: kwordwrap.h:49
KWordWrap::truncatedString
TQString truncatedString(bool dots=true) const
Definition: kwordwrap.cpp:164
KWordWrap::drawFadeoutText
static void drawFadeoutText(TQPainter *p, int x, int y, int maxW, const TQString &t)
Draws the string t at the given coordinates, if it does not fit into maxW the text will be faded out.
Definition: kwordwrap.cpp:181
KWordWrap::formatText
static KWordWrap * formatText(TQFontMetrics &fm, const TQRect &r, int flags, const TQString &str, int len=-1)
Main method for wrapping text.
Definition: kwordwrap.cpp:34
KWordWrap::drawText
void drawText(TQPainter *painter, int x, int y, int flags=TQt::AlignAuto) const
Draw the text that has been previously wrapped, at position x,y.
Definition: kwordwrap.cpp:219
KWordWrap::~KWordWrap
~KWordWrap()
Destructor.
Definition: kwordwrap.cpp:144
KWordWrap::drawTruncateText
static void drawTruncateText(TQPainter *p, int x, int y, int maxW, const TQString &t)
Draws the string t at the given coordinates, if it does not fit into maxW the text will be truncated.
Definition: kwordwrap.cpp:213
KWordWrap::wrappedString
TQString wrappedString() const
Definition: kwordwrap.cpp:148

tdeui

Skip menu "tdeui"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdeui

Skip menu "tdeui"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeui by doxygen 1.9.1
This website is maintained by Timothy Pearson.