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 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 //== INCLUDES =================================================================
51 
52 #include <QPolygonF>
53 #include <QGraphicsItem>
54 #include <QFontMetrics>
55 #include <QPen>
56 #include <QPainter>
57 
58 #include "text.hh"
59 
60 #define BACK_OFFSET 2
61 
62 //== NAMESPACES ===============================================================
63 namespace VSI {
64 
65 //=============================================================================
66 //
67 // CLASS VSI::Text - IMPLEMENTATION
68 //
69 //=============================================================================
70 
72 Text::Text (QGraphicsItem *_parent) :
73  QGraphicsSimpleTextItem (_parent),
74  backgroundSet_ (false),
75  leftOut_(true),
76  rightOut_(true),
77  alignment_ (Qt::AlignLeft),
78  hStretch_ (true)
79 {
80  setBrush (Qt::white);
81 }
82 
83 //------------------------------------------------------------------------------
84 
86 Text::Text (const QString &_text, QGraphicsItem *_parent) :
87  QGraphicsSimpleTextItem (_text, _parent),
88  text_ (_text),
89  backgroundSet_ (false),
90  leftOut_(true),
91  rightOut_(true),
92  alignment_ (Qt::AlignLeft),
93  hStretch_ (true)
94 {
95  setBrush (Qt::white);
96 }
97 
98 //------------------------------------------------------------------------------
99 
102 {
103 }
104 
105 //------------------------------------------------------------------------------
106 
108 void Text::setGeometry (const QRectF &_rect)
109 {
110  QFontMetrics fn (font ());
111 
112  int width = _rect.width ();
113 
114  if (backgroundSet_)
115  {
116  if (rightOut_)
117  width -= _rect.height () / 2;
118  else
119  width -= BACK_OFFSET * 2;
120 
121  if (leftOut_)
122  width -= _rect.height () / 2;
123  else
124  width -= BACK_OFFSET * 2;
125  }
126 
127  if (fn.boundingRect (text_).width () > width)
128  {
129  QString nt = text_ + "...";
130  while (fn.boundingRect (nt).width () > width && nt.length () > 3)
131  nt.remove (nt.length () - 4, 1);
132  QGraphicsSimpleTextItem::setText (nt);
133  }
134  else
135  QGraphicsSimpleTextItem::setText (text_);
136 
137  QGraphicsSimpleTextItem::setPos (_rect.topLeft ());
138  QGraphicsLayoutItem::setGeometry (_rect);
139 }
140 
141 //------------------------------------------------------------------------------
142 
143 // size information for layouting
144 QSizeF Text::sizeHint (Qt::SizeHint _which, const QSizeF &/*_constraint*/) const
145 {
146  QFontMetrics fn (font ());
147  QSizeF sh;
148 
149  int w = 0;
150  if (rightOut_)
151  w += (fn.height () / 2) + (BACK_OFFSET * 2);
152  else
153  w += BACK_OFFSET * 2;
154  if (leftOut_)
155  w += (fn.height () / 2) + (BACK_OFFSET * 2);
156  else
157  w += BACK_OFFSET * 2;
158 
159  QSizeF bOff = QSizeF (w, BACK_OFFSET * 2);
160 
161  switch (_which) {
162  case Qt::MinimumSize:
163  sh = QSizeF(fn.boundingRect ("...").width (), fn.height ());
164  if (backgroundSet_)
165  sh += bOff;
166  break;
167  case Qt::PreferredSize:
168  sh = QSizeF(fn.boundingRect (text_).width (), fn.height ());
169  if (backgroundSet_)
170  sh += bOff;
171  break;
172  case Qt::MaximumSize:
173  sh = QSizeF(fn.boundingRect (text_).width (), fn.height ());
174  if (backgroundSet_)
175  sh += bOff;
176  if (hStretch_)
177  sh += QSizeF (65535, 0);
178  break;
179  case Qt::MinimumDescent:
180  sh = QSizeF(0, fn.descent ());
181  default:
182  break;
183  }
184 
185  return sh;
186 }
187 
188 //------------------------------------------------------------------------------
189 
191 void Text::paint (QPainter *_painter, const QStyleOptionGraphicsItem *_option, QWidget *_widget)
192 {
193  qreal h = geometry ().size ().height () / 2.0;
194 
195  if (backgroundSet_)
196  {
197  QPainterPath path;
198 
199  path.moveTo (geometry ().size ().width () / 2, 0);
200  if (leftOut_)
201  {
202  path.lineTo (h, 0);
203  path.arcTo (0, 0, h * 2.0, h * 2.0, 90, 180);
204  }
205  else
206  {
207  path.lineTo (-h, 0);
208  path.arcTo (-h * 2, 0, h * 2.0, h * 2.0, 90, -180);
209  }
210 
211  if (rightOut_)
212  {
213  path.lineTo (geometry ().size ().width () - h, geometry ().size ().height ());
214  path.arcTo (geometry ().size ().width () - (h * 2), 0, h * 2.0, h * 2.0, -90, 180);
215  }
216  else
217  {
218  path.lineTo (geometry ().size ().width () + h, geometry ().size ().height ());
219  path.arcTo (geometry ().size ().width (), 0, h * 2.0, h * 2.0, -90, -180);
220  }
221  path.lineTo (geometry ().size ().width () / 2, 0);
222 
223  _painter->setBrush (backgroundBrush_);
224  _painter->setPen (backgroundPen_);
225  _painter->drawPath (path);
226 
227 
228  QLinearGradient lG;
229 
230  lG.setStart (0, h);
231  lG.setFinalStop(0, h * 2);
232  lG.setColorAt(0, Qt::transparent);
233  lG.setColorAt(1, QColor (0, 0, 0, 192));
234 
235  _painter->setBrush (lG);
236  _painter->setPen (Qt::NoPen);
237  _painter->drawPath(path);
238 
239  lG.setStart (0, h);
240  lG.setFinalStop(0, 0);
241  lG.setColorAt(0, Qt::transparent);
242  lG.setColorAt(1, QColor (255, 255, 255, 192));
243 
244  QPen pen;
245  pen.setColor (Qt::transparent);
246  pen.setWidthF (4);
247  _painter->setBrush (lG);
248  _painter->setPen (pen);
249  _painter->drawPath(path);
250 
251  if (leftOut_)
252  _painter->translate (h, BACK_OFFSET);
253  else
254  _painter->translate (BACK_OFFSET * 2, BACK_OFFSET);
255  }
256 
257  QFontMetrics fn (font ());
258  int trans;
259  if (alignment_ == Qt::AlignHCenter)
260  {
261  trans = geometry ().size ().width ();
262 
263  if (backgroundSet_)
264  {
265  if (rightOut_)
266  trans -= h;
267  else
268  trans -= BACK_OFFSET * 2;
269  if (leftOut_)
270  trans -= h;
271  else
272  trans -= BACK_OFFSET * 2;
273  }
274 
275  _painter->translate ((trans - fn.boundingRect (QGraphicsSimpleTextItem::text ()).width ()) / 2, 0);
276  }
277  else if (alignment_ == Qt::AlignRight)
278  {
279  trans = geometry ().size ().width ();
280 
281  if (backgroundSet_)
282  {
283  if (rightOut_)
284  trans -= h;
285  else
286  trans -= BACK_OFFSET * 2;
287  if (leftOut_)
288  trans -= h;
289  else
290  trans -= BACK_OFFSET * 2;
291  }
292 
293  _painter->translate (trans - fn.boundingRect (QGraphicsSimpleTextItem::text ()).width (), 0);
294  }
295  else
296  {
297 
298  }
299 
300  QGraphicsSimpleTextItem::paint (_painter, _option, _widget);
301 }
302 
303 //------------------------------------------------------------------------------
304 
306 void Text::setBackground(bool _leftOut, bool _rightOut)
307 {
308  backgroundSet_ = true;
309  leftOut_ = _leftOut;
310  rightOut_ = _rightOut;
311  updateGeometry ();
312 }
313 
314 //------------------------------------------------------------------------------
315 
317 void Text::setAlignment(Qt::Alignment _alignment)
318 {
319  if (_alignment & Qt::AlignLeft)
320  alignment_ = Qt::AlignLeft;
321  else if (_alignment & Qt::AlignHCenter)
322  alignment_ = Qt::AlignHCenter;
323  else if (_alignment & Qt::AlignRight)
324  alignment_ = Qt::AlignRight;
325 }
326 
327 //------------------------------------------------------------------------------
328 
330 void Text::setHorizontalStretch(bool _stretch)
331 {
332  hStretch_ = _stretch;
333  updateGeometry ();
334 }
335 
336 //------------------------------------------------------------------------------
337 
340 {
341  backgroundSet_ = false;
342  updateGeometry ();
343 }
344 
345 //------------------------------------------------------------------------------
346 
348 QRectF Text::boundingRect() const
349 {
350  QFontMetrics fn (font ());
351  int x, w;
352 
353  if (!backgroundSet_)
354  {
355  QRectF rect = QGraphicsSimpleTextItem::boundingRect ();
356 
357  if (alignment_ == Qt::AlignHCenter)
358  rect.translate ((geometry ().size ().width () - fn.boundingRect (QGraphicsSimpleTextItem::text ()).width ()) / 2, 0);
359  else if (alignment_ == Qt::AlignRight)
360  rect.translate (geometry ().size ().width () - fn.boundingRect (QGraphicsSimpleTextItem::text ()).width (), 0);
361 
362  return rect;
363  }
364 
365  w = geometry ().size ().width ();
366  x = 0;
367 
368  if (!leftOut_)
369  {
370  w += (fn.height () / 2) + (BACK_OFFSET * 2);
371  x -= (fn.height () / 2) + (BACK_OFFSET * 2);
372  }
373 
374  if (!rightOut_)
375  {
376  w += (fn.height () / 2) + (BACK_OFFSET * 2);
377  }
378 
379  return QRectF (QPointF (x, 0), QSizeF(w, geometry ().size ().height ()));
380 }
381 
382 //------------------------------------------------------------------------------
383 
385 void Text::setBackgroundBrush(QBrush _brush)
386 {
387  backgroundBrush_ = _brush;
388  update ();
389 }
390 
391 //------------------------------------------------------------------------------
392 
394 void Text::setBackgroundPen(QPen _pen)
395 {
396  backgroundPen_ = _pen;
397  update ();
398 }
399 
400 //------------------------------------------------------------------------------
401 
403 QPainterPath Text::shape() const
404 {
405  if (!backgroundSet_)
406  {
407  QPainterPath shape = QGraphicsSimpleTextItem::shape ();
408 
409  QFontMetrics fn (font ());
410 
411  if (alignment_ == Qt::AlignHCenter || alignment_ == Qt::AlignRight)
412  {
413  QTransform trans;
414  if (alignment_ == Qt::AlignHCenter)
415  trans = QTransform::fromTranslate ((geometry ().size ().width () - fn.boundingRect (QGraphicsSimpleTextItem::text ()).width ()) / 2, 0);
416  else if (alignment_ == Qt::AlignRight)
417  trans = QTransform::fromTranslate (geometry ().size ().width () - fn.boundingRect (QGraphicsSimpleTextItem::text ()).width (), 0);
418 
419  QList<QPolygonF> poly = shape.toSubpathPolygons (trans);
420 
421  shape = QPainterPath ();
422 
423  foreach (const QPolygonF &p, poly)
424  shape.addPolygon(p);
425  }
426 
427  return shape;
428  }
429 
430  qreal h = geometry ().size ().height () / 2.0;
431 
432  QPainterPath path;
433 
434  path.moveTo (geometry ().size ().width () / 2, 0);
435  if (leftOut_)
436  {
437  path.lineTo (h, 0);
438  path.arcTo (0, 0, h * 2.0, h * 2.0, 90, 180);
439  }
440  else
441  {
442  path.lineTo (-h, 0);
443  path.arcTo (-h * 2, 0, h * 2.0, h * 2.0, 90, -180);
444  }
445 
446  if (rightOut_)
447  {
448  path.lineTo (geometry ().size ().width () - h, geometry ().size ().height ());
449  path.arcTo (geometry ().size ().width () - (h * 2), 0, h * 2.0, h * 2.0, -90, 180);
450  }
451  else
452  {
453  path.lineTo (geometry ().size ().width () + h, geometry ().size ().height ());
454  path.arcTo (geometry ().size ().width (), 0, h * 2.0, h * 2.0, -90, -180);
455  }
456  path.lineTo (geometry ().size ().width () / 2, 0);
457 
458  return path;
459 }
460 
461 //------------------------------------------------------------------------------
462 }
463 
virtual void setBackgroundBrush(QBrush _brush)
Sets the background brush.
Definition: text.cc:385
void clearBackground()
Disables backgorund painting.
Definition: text.cc:339
virtual QRectF boundingRect() const
Bounding rectangle.
Definition: text.cc:348
void setHorizontalStretch(bool _stretch)
Should this widget be stretchable in horizontal direction.
Definition: text.cc:330
void setAlignment(Qt::Alignment _alignment)
Placement of the text in a stretched widget.
Definition: text.cc:317
void setBackground(bool _leftOut, bool _rightOut)
Enables background painting.
Definition: text.cc:306
virtual void setGeometry(const QRectF &_rect)
Sets the geometry.
Definition: text.cc:108
virtual void paint(QPainter *_painter, const QStyleOptionGraphicsItem *_option, QWidget *_widget=0)
Background painting.
Definition: text.cc:191
QPainterPath shape() const
Returns the shape for proper repainting/event handling.
Definition: text.cc:403
Text(QGraphicsItem *_parent=0)
Constructor.
Definition: text.cc:72
~Text()
Destrucotr.
Definition: text.cc:101
virtual void setBackgroundPen(QPen _pen)
Sets the background pen.
Definition: text.cc:394