Developer Documentation
text.cc
1/*===========================================================================*\
2* *
3* OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39* *
40\*===========================================================================*/
41
42
43
44//== INCLUDES =================================================================
45
46#include <QPolygonF>
47#include <QGraphicsItem>
48#include <QFontMetrics>
49#include <QPen>
50#include <QPainter>
51
52#include "text.hh"
53
54#define BACK_OFFSET 2
55
56//== NAMESPACES ===============================================================
57namespace VSI {
58
59//=============================================================================
60//
61// CLASS VSI::Text - IMPLEMENTATION
62//
63//=============================================================================
64
66Text::Text (QGraphicsItem *_parent) :
67 QGraphicsSimpleTextItem (_parent),
68 backgroundSet_ (false),
69 leftOut_(true),
70 rightOut_(true),
71 alignment_ (Qt::AlignLeft),
72 hStretch_ (true)
73{
74 setBrush (Qt::white);
75}
76
77//------------------------------------------------------------------------------
78
80Text::Text (const QString &_text, QGraphicsItem *_parent) :
81 QGraphicsSimpleTextItem (_text, _parent),
82 text_ (_text),
83 backgroundSet_ (false),
84 leftOut_(true),
85 rightOut_(true),
86 alignment_ (Qt::AlignLeft),
87 hStretch_ (true)
88{
89 setBrush (Qt::white);
90}
91
92//------------------------------------------------------------------------------
93
96{
97}
98
99//------------------------------------------------------------------------------
100
102void Text::setGeometry (const QRectF &_rect)
103{
104 QFontMetrics fn (font ());
105
106 int width = _rect.width ();
107
108 if (backgroundSet_)
109 {
110 if (rightOut_)
111 width -= _rect.height () / 2;
112 else
113 width -= BACK_OFFSET * 2;
114
115 if (leftOut_)
116 width -= _rect.height () / 2;
117 else
118 width -= BACK_OFFSET * 2;
119 }
120
121 if (fn.boundingRect (text_).width () > width)
122 {
123 QString nt = text_ + "...";
124 while (fn.boundingRect (nt).width () > width && nt.length () > 3)
125 nt.remove (nt.length () - 4, 1);
126 QGraphicsSimpleTextItem::setText (nt);
127 }
128 else
129 QGraphicsSimpleTextItem::setText (text_);
130
131 QGraphicsSimpleTextItem::setPos (_rect.topLeft ());
132 QGraphicsLayoutItem::setGeometry (_rect);
133}
134
135//------------------------------------------------------------------------------
136
137// size information for layouting
138QSizeF Text::sizeHint (Qt::SizeHint _which, const QSizeF &/*_constraint*/) const
139{
140 QFontMetrics fn (font ());
141 QSizeF sh;
142
143 int w = 0;
144 if (rightOut_)
145 w += (fn.height () / 2) + (BACK_OFFSET * 2);
146 else
147 w += BACK_OFFSET * 2;
148 if (leftOut_)
149 w += (fn.height () / 2) + (BACK_OFFSET * 2);
150 else
151 w += BACK_OFFSET * 2;
152
153 QSizeF bOff = QSizeF (w, BACK_OFFSET * 2);
154
155 switch (_which) {
156 case Qt::MinimumSize:
157 sh = QSizeF(fn.boundingRect ("...").width (), fn.height ());
158 if (backgroundSet_)
159 sh += bOff;
160 break;
161 case Qt::PreferredSize:
162 sh = QSizeF(fn.boundingRect (text_).width (), fn.height ());
163 if (backgroundSet_)
164 sh += bOff;
165 break;
166 case Qt::MaximumSize:
167 sh = QSizeF(fn.boundingRect (text_).width (), fn.height ());
168 if (backgroundSet_)
169 sh += bOff;
170 if (hStretch_)
171 sh += QSizeF (65535, 0);
172 break;
173 case Qt::MinimumDescent:
174 sh = QSizeF(0, fn.descent ());
175 default:
176 break;
177 }
178
179 return sh;
180}
181
182//------------------------------------------------------------------------------
183
185void Text::paint (QPainter *_painter, const QStyleOptionGraphicsItem *_option, QWidget *_widget)
186{
187 qreal h = geometry ().size ().height () / 2.0;
188
189 if (backgroundSet_)
190 {
191 QPainterPath path;
192
193 path.moveTo (geometry ().size ().width () / 2, 0);
194 if (leftOut_)
195 {
196 path.lineTo (h, 0);
197 path.arcTo (0, 0, h * 2.0, h * 2.0, 90, 180);
198 }
199 else
200 {
201 path.lineTo (-h, 0);
202 path.arcTo (-h * 2, 0, h * 2.0, h * 2.0, 90, -180);
203 }
204
205 if (rightOut_)
206 {
207 path.lineTo (geometry ().size ().width () - h, geometry ().size ().height ());
208 path.arcTo (geometry ().size ().width () - (h * 2), 0, h * 2.0, h * 2.0, -90, 180);
209 }
210 else
211 {
212 path.lineTo (geometry ().size ().width () + h, geometry ().size ().height ());
213 path.arcTo (geometry ().size ().width (), 0, h * 2.0, h * 2.0, -90, -180);
214 }
215 path.lineTo (geometry ().size ().width () / 2, 0);
216
217 _painter->setBrush (backgroundBrush_);
218 _painter->setPen (backgroundPen_);
219 _painter->drawPath (path);
220
221
222 QLinearGradient lG;
223
224 lG.setStart (0, h);
225 lG.setFinalStop(0, h * 2);
226 lG.setColorAt(0, Qt::transparent);
227 lG.setColorAt(1, QColor (0, 0, 0, 192));
228
229 _painter->setBrush (lG);
230 _painter->setPen (Qt::NoPen);
231 _painter->drawPath(path);
232
233 lG.setStart (0, h);
234 lG.setFinalStop(0, 0);
235 lG.setColorAt(0, Qt::transparent);
236 lG.setColorAt(1, QColor (255, 255, 255, 192));
237
238 QPen pen;
239 pen.setColor (Qt::transparent);
240 pen.setWidthF (4);
241 _painter->setBrush (lG);
242 _painter->setPen (pen);
243 _painter->drawPath(path);
244
245 if (leftOut_)
246 _painter->translate (h, BACK_OFFSET);
247 else
248 _painter->translate (BACK_OFFSET * 2, BACK_OFFSET);
249 }
250
251 QFontMetrics fn (font ());
252 int trans;
253 if (alignment_ == Qt::AlignHCenter)
254 {
255 trans = geometry ().size ().width ();
256
257 if (backgroundSet_)
258 {
259 if (rightOut_)
260 trans -= h;
261 else
262 trans -= BACK_OFFSET * 2;
263 if (leftOut_)
264 trans -= h;
265 else
266 trans -= BACK_OFFSET * 2;
267 }
268
269 _painter->translate ((trans - fn.boundingRect (QGraphicsSimpleTextItem::text ()).width ()) / 2, 0);
270 }
271 else if (alignment_ == Qt::AlignRight)
272 {
273 trans = geometry ().size ().width ();
274
275 if (backgroundSet_)
276 {
277 if (rightOut_)
278 trans -= h;
279 else
280 trans -= BACK_OFFSET * 2;
281 if (leftOut_)
282 trans -= h;
283 else
284 trans -= BACK_OFFSET * 2;
285 }
286
287 _painter->translate (trans - fn.boundingRect (QGraphicsSimpleTextItem::text ()).width (), 0);
288 }
289 else
290 {
291
292 }
293
294 QGraphicsSimpleTextItem::paint (_painter, _option, _widget);
295}
296
297//------------------------------------------------------------------------------
298
300void Text::setBackground(bool _leftOut, bool _rightOut)
301{
302 backgroundSet_ = true;
303 leftOut_ = _leftOut;
304 rightOut_ = _rightOut;
305 updateGeometry ();
306}
307
308//------------------------------------------------------------------------------
309
311void Text::setAlignment(Qt::Alignment _alignment)
312{
313 if (_alignment & Qt::AlignLeft)
314 alignment_ = Qt::AlignLeft;
315 else if (_alignment & Qt::AlignHCenter)
316 alignment_ = Qt::AlignHCenter;
317 else if (_alignment & Qt::AlignRight)
318 alignment_ = Qt::AlignRight;
319}
320
321//------------------------------------------------------------------------------
322
324void Text::setHorizontalStretch(bool _stretch)
325{
326 hStretch_ = _stretch;
327 updateGeometry ();
328}
329
330//------------------------------------------------------------------------------
331
334{
335 backgroundSet_ = false;
336 updateGeometry ();
337}
338
339//------------------------------------------------------------------------------
340
342QRectF Text::boundingRect() const
343{
344 QFontMetrics fn (font ());
345 int x, w;
346
347 if (!backgroundSet_)
348 {
349 QRectF rect = QGraphicsSimpleTextItem::boundingRect ();
350
351 if (alignment_ == Qt::AlignHCenter)
352 rect.translate ((geometry ().size ().width () - fn.boundingRect (QGraphicsSimpleTextItem::text ()).width ()) / 2, 0);
353 else if (alignment_ == Qt::AlignRight)
354 rect.translate (geometry ().size ().width () - fn.boundingRect (QGraphicsSimpleTextItem::text ()).width (), 0);
355
356 return rect;
357 }
358
359 w = geometry ().size ().width ();
360 x = 0;
361
362 if (!leftOut_)
363 {
364 w += (fn.height () / 2) + (BACK_OFFSET * 2);
365 x -= (fn.height () / 2) + (BACK_OFFSET * 2);
366 }
367
368 if (!rightOut_)
369 {
370 w += (fn.height () / 2) + (BACK_OFFSET * 2);
371 }
372
373 return QRectF (QPointF (x, 0), QSizeF(w, geometry ().size ().height ()));
374}
375
376//------------------------------------------------------------------------------
377
379void Text::setBackgroundBrush(QBrush _brush)
380{
381 backgroundBrush_ = _brush;
382 update ();
383}
384
385//------------------------------------------------------------------------------
386
389{
390 backgroundPen_ = _pen;
391 update ();
392}
393
394//------------------------------------------------------------------------------
395
397QPainterPath Text::shape() const
398{
399 if (!backgroundSet_)
400 {
401 QPainterPath shape = QGraphicsSimpleTextItem::shape ();
402
403 QFontMetrics fn (font ());
404
405 if (alignment_ == Qt::AlignHCenter || alignment_ == Qt::AlignRight)
406 {
407 QTransform trans;
408 if (alignment_ == Qt::AlignHCenter)
409 trans = QTransform::fromTranslate ((geometry ().size ().width () - fn.boundingRect (QGraphicsSimpleTextItem::text ()).width ()) / 2, 0);
410 else if (alignment_ == Qt::AlignRight)
411 trans = QTransform::fromTranslate (geometry ().size ().width () - fn.boundingRect (QGraphicsSimpleTextItem::text ()).width (), 0);
412
413 QList<QPolygonF> poly = shape.toSubpathPolygons (trans);
414
415 shape = QPainterPath ();
416
417 foreach (const QPolygonF &p, poly)
418 shape.addPolygon(p);
419 }
420
421 return shape;
422 }
423
424 qreal h = geometry ().size ().height () / 2.0;
425
426 QPainterPath path;
427
428 path.moveTo (geometry ().size ().width () / 2, 0);
429 if (leftOut_)
430 {
431 path.lineTo (h, 0);
432 path.arcTo (0, 0, h * 2.0, h * 2.0, 90, 180);
433 }
434 else
435 {
436 path.lineTo (-h, 0);
437 path.arcTo (-h * 2, 0, h * 2.0, h * 2.0, 90, -180);
438 }
439
440 if (rightOut_)
441 {
442 path.lineTo (geometry ().size ().width () - h, geometry ().size ().height ());
443 path.arcTo (geometry ().size ().width () - (h * 2), 0, h * 2.0, h * 2.0, -90, 180);
444 }
445 else
446 {
447 path.lineTo (geometry ().size ().width () + h, geometry ().size ().height ());
448 path.arcTo (geometry ().size ().width (), 0, h * 2.0, h * 2.0, -90, -180);
449 }
450 path.lineTo (geometry ().size ().width () / 2, 0);
451
452 return path;
453}
454
455//------------------------------------------------------------------------------
456}
457
virtual QRectF boundingRect() const
Bounding rectangle.
Definition: text.cc:342
virtual void paint(QPainter *_painter, const QStyleOptionGraphicsItem *_option, QWidget *_widget=0)
Background painting.
Definition: text.cc:185
Text(QGraphicsItem *_parent=0)
Constructor.
Definition: text.cc:66
virtual void setBackgroundBrush(QBrush _brush)
Sets the background brush.
Definition: text.cc:379
void setAlignment(Qt::Alignment _alignment)
Placement of the text in a stretched widget.
Definition: text.cc:311
void clearBackground()
Disables backgorund painting.
Definition: text.cc:333
virtual void setGeometry(const QRectF &_rect)
Sets the geometry.
Definition: text.cc:102
virtual void setBackgroundPen(QPen _pen)
Sets the background pen.
Definition: text.cc:388
void setHorizontalStretch(bool _stretch)
Should this widget be stretchable in horizontal direction.
Definition: text.cc:324
void setBackground(bool _leftOut, bool _rightOut)
Enables background painting.
Definition: text.cc:300
~Text()
Destrucotr.
Definition: text.cc:95
QPainterPath shape() const
Returns the shape for proper repainting/event handling.
Definition: text.cc:397