• 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
24class KWordWrapPrivate {
25public:
26 TQRect m_constrainingRect;
27};
28
29KWordWrap::KWordWrap(const TQRect & r) {
30 d = new KWordWrapPrivate;
31 d->m_constrainingRect = r;
32}
33
34KWordWrap* 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
144KWordWrap::~KWordWrap() {
145 delete d;
146}
147
148TQString 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
164TQString 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
175static 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
181void 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
213void 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
219void 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.4
This website is maintained by Timothy Pearson.