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 ===============================================================
57 namespace VSI {
58
59 //=============================================================================
60 //
61 // CLASS VSI::Text - IMPLEMENTATION
62 //
63 //=============================================================================
64
66 Text::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
80 Text::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
95 Text::~Text ()
96 {
97 }
98
99 //------------------------------------------------------------------------------
100
102 void 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
138 QSizeF 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
185 void 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
300 void Text::setBackground(bool _leftOut, bool _rightOut)
301 {
302 backgroundSet_ = true;
303 leftOut_ = _leftOut;
304 rightOut_ = _rightOut;
305 updateGeometry ();
306 }
307
308 //------------------------------------------------------------------------------
309
311 void 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
324 void Text::setHorizontalStretch(bool _stretch)
325 {
326 hStretch_ = _stretch;
327 updateGeometry ();
328 }
329
330 //------------------------------------------------------------------------------
331
333 void Text::clearBackground()
334 {
335 backgroundSet_ = false;
336 updateGeometry ();
337 }
338
339 //------------------------------------------------------------------------------
340
342 QRectF 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
379 void Text::setBackgroundBrush(QBrush _brush)
380 {
381 backgroundBrush_ = _brush;
382 update ();
383 }
384
385 //------------------------------------------------------------------------------
386
388 void Text::setBackgroundPen(QPen _pen)
389 {
390 backgroundPen_ = _pen;
391 update ();
392 }
393
394 //------------------------------------------------------------------------------
395
397 QPainterPath 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
VSI::Text::setAlignment
void setAlignment(Qt::Alignment _alignment)
Placement of the text in a stretched widget.
Definition: text.cc:311
VSI::Text::shape
QPainterPath shape() const
Returns the shape for proper repainting/event handling.
Definition: text.cc:397
VSI::Text::setGeometry
virtual void setGeometry(const QRectF &_rect)
Sets the geometry.
Definition: text.cc:102
VSI::Text::clearBackground
void clearBackground()
Disables backgorund painting.
Definition: text.cc:333
VSI::Text::setBackgroundPen
virtual void setBackgroundPen(QPen _pen)
Sets the background pen.
Definition: text.cc:388
VSI::Text::~Text
~Text()
Destrucotr.
Definition: text.cc:95
VSI::Text::paint
virtual void paint(QPainter *_painter, const QStyleOptionGraphicsItem *_option, QWidget *_widget=0)
Background painting.
Definition: text.cc:185
VSI::Text::Text
Text(QGraphicsItem *_parent=0)
Constructor.
Definition: text.cc:66
VSI::Text::setBackgroundBrush
virtual void setBackgroundBrush(QBrush _brush)
Sets the background brush.
Definition: text.cc:379
VSI::Text::boundingRect
virtual QRectF boundingRect() const
Bounding rectangle.
Definition: text.cc:342
Qt
VSI
Definition: baseWidget.cc:72
VSI::Text::setBackground
void setBackground(bool _leftOut, bool _rightOut)
Enables background painting.
Definition: text.cc:300
VSI::Text::setHorizontalStretch
void setHorizontalStretch(bool _stretch)
Should this widget be stretchable in horizontal direction.
Definition: text.cc:324