All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ObjectItem.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2001-2014 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file ObjectItem.cpp
22 
23  \brief
24 
25  \ingroup layout
26 */
27 
28 // TerraLib
29 #include "ObjectItem.h"
30 #include "ItemController.h"
31 #include "Context.h"
32 #include "AbstractScene.h"
33 #include "ItemModelObservable.h"
34 #include "Scene.h"
35 #include "../../../color/RGBAColor.h"
36 #include "../../../../qt/widgets/Utils.h"
37 #include "../../../../geometry/Envelope.h"
38 #include "../../../../common/STLUtils.h"
39 
40 // Qt
41 #include <QGraphicsSceneHoverEvent>
42 #include <QGraphicsSceneMouseEvent>
43 #include <QCursor>
44 #include <QStyleOptionGraphicsItem>
45 
47  QGraphicsObject(0),
48  ItemObserver(controller, o),
49  m_mousePressedCtrl(false),
50  m_hoverAboveItem(false),
51  m_toResizeItem(false),
52  m_enumSides(TPNoneSide)
53 {
54  QGraphicsItem* item = this;
56 
57  //If enabled is true, this item will accept hover events
58  setAcceptHoverEvents(true);
59 }
60 
62 {
63 
64 }
65 
67 {
68  QPointF posF = scenePos();
69  qreal valuex = posF.x();
70  qreal valuey = posF.y();
71 
72  te::gm::Coord2D coordinate;
73  coordinate.x = valuex;
74  coordinate.y = valuey;
75 
76  return coordinate;
77 }
78 
79 void te::layout::ObjectItem::setPos( const QPointF &pos )
80 {
81  QGraphicsItem::setPos(pos);
82 
83  refresh();
84 }
85 
86 void te::layout::ObjectItem::setPixmap( const QPixmap& pixmap )
87 {
88  m_pixmap = pixmap;
89 
90  if(m_pixmap.isNull())
91  return;
92 
93  Utils* utils = Context::getInstance()->getUtils();
94  QPointF point = pos();
95 
96  Observable* model = (Observable*)m_controller->getModel();
97  te::gm::Envelope box = model->getBox();
98 
99  //If you modify the boundingRect value, you need to inform Graphics View about it by calling QGraphicsItem::prepareGeometryChange();
100  QGraphicsObject::prepareGeometryChange();
101  //The rect is in coordinate location of the item, because the bounding rect is
102  //updated with this value, and will be used by the scene for drawing.
103  //Rect values ​​do not influence the actual position of the object.
104  setRect(QRectF(0, 0, box.getWidth(), box.getHeight()));
105  update();
106 }
107 
108 void te::layout::ObjectItem::paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget /*= 0 */ )
109 {
110  Q_UNUSED( option );
111  Q_UNUSED( widget );
112  if ( !painter )
113  {
114  return;
115  }
116 
117  drawBackground( painter );
118 
119  QRectF boundRect;
120  boundRect = boundingRect();
121 
122  painter->save();
123  painter->translate( -boundRect.bottomLeft().x(), -boundRect.topRight().y() );
124  painter->drawPixmap(boundRect, m_pixmap, QRectF( 0, 0, m_pixmap.width(), m_pixmap.height() ));
125  painter->restore();
126 
127  //Draw Selection
128  if (option->state & QStyle::State_Selected)
129  {
130  drawSelection(painter);
131  }
132 }
133 
134 void te::layout::ObjectItem::drawBackground( QPainter * painter )
135 {
136  if (painter)
137  {
138  //painter->setBrush(brush());
139  painter->setPen(Qt::NoPen);
140  painter->setRenderHint( QPainter::Antialiasing, true );
141  painter->drawRect(QRectF( 0, 0, boundingRect().width(), boundingRect().height()));
142  }
143 }
144 
145 void te::layout::ObjectItem::drawSelection( QPainter* painter )
146 {
147  if(!painter)
148  {
149  return;
150  }
151 
152  qreal penWidth = painter->pen().widthF();
153 
154  const qreal adj = penWidth / 2;
155  const QColor fgcolor(255,255,255);
156  const QColor backgroundColor(0,0,0);
157 
158  painter->setPen(QPen(backgroundColor, 0, Qt::SolidLine));
159  painter->setBrush(Qt::NoBrush);
160  painter->drawRect(boundingRect().adjusted(adj, adj, -adj, -adj));
161 
162  painter->setPen(QPen(fgcolor, 0, Qt::DashLine));
163  painter->setBrush(Qt::NoBrush);
164  painter->drawRect(boundingRect().adjusted(adj, adj, -adj, -adj));
165 }
166 
168 {
169  return m_rect;
170 }
171 
173 {
174  if (rect.isEmpty() && !rect.isNull())
175  return;
176 
177  m_rect = rect;
178  update(rect);
179 }
180 
181 void te::layout::ObjectItem::mousePressEvent( QGraphicsSceneMouseEvent * event )
182 {
183  QGraphicsItem::mousePressEvent(event);
184 
185  if(event->modifiers() == Qt::AltModifier && m_toResizeItem)
186  {
187  m_clonePixmap = getPixmap();
188  m_mousePressedCtrl = true;
189  }
190 }
191 
192 void te::layout::ObjectItem::mouseReleaseEvent( QGraphicsSceneMouseEvent * event )
193 {
194  QGraphicsItem::mouseReleaseEvent(event);
195 
196  te::gm::Envelope boxScene = createNewBoxInCoordScene(event->scenePos().x(), event->scenePos().y());
197  if(boxScene.isValid() && boxScene.getWidth() > 0 && boxScene.getHeight() > 0)
198  m_controller->setBox(boxScene);
199 
200  m_mousePressedCtrl = false;
201 
202  if(m_toResizeItem && boxScene.isValid())
203  {
204  m_toResizeItem = false;
205  //Antes é necessário saber se o pixmap continua o mesmo, ou foi modificado.
206  //Só chamará o redraw se foi modificado.
207 
208  double zoomfactor = Context::getInstance()->getZoomFactor();
209  redraw(zoomfactor);
210  setOpacity(1.);
211  }
212 
213  refresh();
214 }
215 
216 void te::layout::ObjectItem::mouseMoveEvent( QGraphicsSceneMouseEvent * event )
217 {
218  if(event->modifiers() == Qt::AltModifier && event->buttons() == Qt::LeftButton && m_toResizeItem)
219  {
220  m_mousePressedCtrl = true;
221  setOpacity(0.5);
222 
223  QPixmap pix = calculateNewPixmap(event->scenePos().x(), event->scenePos().y());
224  setPixmap(pix);
225  update();
226  }
227  else
228  {
229  if(!m_toResizeItem)
230  setOpacity(1.);
231  m_mousePressedCtrl = false;
232  QGraphicsItem::mouseMoveEvent(event);
233  }
234 }
235 
236 void te::layout::ObjectItem::hoverEnterEvent( QGraphicsSceneHoverEvent * event )
237 {
238  QGraphicsItem::hoverEnterEvent(event);
239 }
240 
241 void te::layout::ObjectItem::hoverLeaveEvent( QGraphicsSceneHoverEvent * event )
242 {
243  m_hoverAboveItem = false;
244  setCursor(Qt::ArrowCursor);
245  QGraphicsItem::hoverLeaveEvent(event);
246 }
247 
248 void te::layout::ObjectItem::hoverMoveEvent( QGraphicsSceneHoverEvent * event )
249 {
250  m_hoverAboveItem = true;
251  m_toResizeItem = checkTouchesCorner(event->pos().x(), event->pos().y());
252  QGraphicsItem::hoverMoveEvent(event);
253 }
254 
255 bool te::layout::ObjectItem::checkTouchesCorner( const double& x, const double& y )
256 {
257  bool result = true;
258  QRectF bRect = boundingRect();
259  double margin = 2.; //precision
260 
261  QPointF ll = bRect.bottomLeft();
262  QPointF lr = bRect.bottomRight();
263  QPointF tl = bRect.topLeft();
264  QPointF tr = bRect.topRight();
265 
266  if((x >= (ll.x() - margin) && x <= (ll.x() + margin))
267  && (y >= (ll.y() - margin) && y <= (ll.y() + margin)))
268  {
269  setCursor(Qt::SizeBDiagCursor);
270  m_enumSides = TPLowerLeft;
271  }
272  else if((x >= (lr.x() - margin) && x <= (lr.x() + margin))
273  && (y >= (lr.y() - margin) && y <= (lr.y() + margin)))
274  {
275  setCursor(Qt::SizeFDiagCursor);
276  m_enumSides = TPLowerRight;
277  }
278  else if((x >= (tl.x() - margin) && x <= (tl.x() + margin))
279  && (y >= (tl.y() - margin) && y <= (tl.y() + margin)))
280  {
281  setCursor(Qt::SizeFDiagCursor);
282  m_enumSides = TPTopLeft;
283  }
284  else if((x >= (tr.x() - margin) && x <= (tr.x() + margin))
285  && (y >= (tr.y() - margin) && y <= (tr.y() + margin)))
286  {
287  setCursor(Qt::SizeBDiagCursor);
288  m_enumSides = TPTopRight;
289  }
290  else
291  {
292  setCursor(Qt::ArrowCursor);
293  m_enumSides = TPNoneSide;
294  result = false;
295  }
296 
297  return result;
298 }
299 
300 QPixmap te::layout::ObjectItem::calculateNewPixmap( const double& x, const double& y )
301 {
302  te::gm::Envelope boxScene = createNewBoxInCoordScene(x, y);
303  QPixmap pix = getPixmap().scaled(boxScene.getWidth(), boxScene.getHeight());
304 
305  if(pix.isNull())
306  pix = getPixmap();
307 
308  return pix;
309 }
310 
312 {
313  te::gm::Envelope boxScene = m_model->getBox();;
314 
315  QPointF posItem = this->scenePos();
316  QPointF posAtual(x, y);
317 
318  double xTranslation = 0;
319  double yTranslation = 0;
320 
321  double x1 = posItem.x() < posAtual.x() ? posItem.x() : posAtual.x();
322  double y1 = posItem.y() < posAtual.y() ? posItem.y() : posAtual.y();
323  double x2 = posItem.x() > posAtual.x() ? posItem.x() : posAtual.x();
324  double y2 = posItem.y() > posAtual.y() ? posItem.y() : posAtual.y();
325 
326  double dx = x2 - x1;
327  double dy = y2 - y1;
328 
329  if(m_mousePressedCtrl && m_toResizeItem)
330  {
331  switch(m_enumSides)
332  {
333  case TPLowerRight :
334  {
335  boxScene = te::gm::Envelope(posItem.x(), posItem.y() - dy, posItem.x() + dx, posItem.y());
336  break;
337  }
338  case TPLowerLeft:
339  {
340  dx = posItem.x() - posAtual.x();
341  dy = posItem.y() - posAtual.y();
342 
343  QPointF pbxy2 = mapToScene(boundingRect().topRight());
344  if(posAtual.x() < pbxy2.x() && posAtual.y() < posItem.y())
345  {
346  boxScene = te::gm::Envelope(posItem.x() - dx, posItem.y() - dy, pbxy2.x(), posItem.y());
347 
348  QPointF p_f = mapFromScene(QPointF(posItem.x() - dx, posItem.y()));
349  QPointF p_ff = mapToParent(p_f);
350  xTranslation = p_ff.x();
351  yTranslation = p_ff.y();
352 
353  //In Parent Coordinates
354  setPos( QPointF(xTranslation, yTranslation) );
355  }
356  break;
357  }
358  case TPTopRight:
359  {
360 
361  QRectF bond = boundingRect();
362 
363  QPointF pbxy2 = mapToScene(boundingRect().topRight());
364 
365  dx = posAtual.x() - pbxy2.x();
366  dy = posAtual.y() - pbxy2.y();
367 
368  QPointF pbxy1 = mapToScene(boundingRect().bottomLeft());
369  if(posAtual.x() > posItem.x() && posAtual.y() < pbxy1.y())
370  {
371  boxScene = te::gm::Envelope(boxScene.getLowerLeftX(),
372  boxScene.getLowerLeftY(), pbxy2.x() + dx, posItem.y() + dy);
373 
374  QPointF p_f = mapFromScene(QPointF(posItem.x(), posItem.y() + dy));
375  QPointF p_ff = mapToParent(p_f);
376  xTranslation = p_ff.x();
377  yTranslation = p_ff.y();
378 
379  //In Parent Coordinates
380  setPos( QPointF(xTranslation, yTranslation) );
381  }
382  break;
383  }
384  case TPTopLeft :
385  {
386  QPointF pbxy2 = mapToScene(boundingRect().topLeft());
387 
388  dx = posAtual.x() - pbxy2.x();
389  dy = posAtual.y() - pbxy2.y();
390 
391  QPointF pbxy1 = mapToScene(boundingRect().bottomRight());
392  if(posAtual.x() < pbxy1.x() && posAtual.y() > pbxy1.y())
393  {
394  boxScene = te::gm::Envelope(posItem.x() + dx, pbxy1.y(), pbxy1.x(), posItem.y() + dy);
395 
396  QPointF p_f = mapFromScene(QPointF(posItem.x() + dx, posItem.y() + dy));
397  QPointF p_ff = mapToParent(p_f);
398  xTranslation = p_ff.x();
399  yTranslation = p_ff.y();
400 
401  //In Parent Coordinates
402  setPos( QPointF(xTranslation, yTranslation) );
403  }
404  break;
405  }
406  default :
407  {
408  boxScene = te::gm::Envelope(posItem.x(), posItem.y() - boundingRect().height(),
409  posItem.x() + boundingRect().width(), posItem.y());
410  break;
411  }
412  }
413  }
414 
415  return boxScene;
416 }
417 
418 bool te::layout::ObjectItem::contains( const QPointF &point ) const
419 {
420  return m_controller->contains(te::gm::Coord2D(point.x(), point.y()));
421 }
422 
424 {
425  return m_pixmap;
426 }
427 
429 {
430  QGraphicsItem::setZValue(z);
431  setZValueItem(z);
432 }
433 
435 {
436  return QGraphicsItem::zValue();
437 }
438 
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=0)
Definition: ObjectItem.cpp:108
double y
y-coordinate.
Definition: Coord2D.h:87
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
Definition: ObjectItem.cpp:216
virtual void setPixmap(const QPixmap &pixmap)
Definition: ObjectItem.cpp:86
double x
x-coordinate.
Definition: Coord2D.h:86
virtual QPixmap getPixmap()
Definition: ObjectItem.cpp:423
virtual te::gm::Envelope getBox()=0
virtual void drawSelection(QPainter *painter)
Definition: ObjectItem.cpp:145
virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event)
Definition: ObjectItem.cpp:248
const double & getLowerLeftY() const
It returns a constant refernce to the y coordinate of the lower left corner.
Definition: Envelope.h:400
double getWidth() const
It returns the envelope width.
Definition: Envelope.h:443
virtual void drawBackground(QPainter *painter)
Definition: ObjectItem.cpp:134
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
virtual bool checkTouchesCorner(const double &x, const double &y)
Definition: ObjectItem.cpp:255
virtual void setRect(QRectF rect)
Definition: ObjectItem.cpp:172
An Envelope defines a 2D rectangular region.
Definition: Envelope.h:51
virtual void insertItem(ItemObserver *item)=0
void setZValue(qreal z)
Definition: ObjectItem.cpp:428
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event)
Definition: ObjectItem.cpp:181
Utils * getUtils()
Definition: Context.cpp:126
virtual te::gm::Envelope createNewBoxInCoordScene(const double &x, const double &y)
Definition: ObjectItem.cpp:311
virtual int getZValueItem()
Definition: ObjectItem.cpp:434
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
Definition: ObjectItem.cpp:192
virtual QPixmap calculateNewPixmap(const double &x, const double &y)
Definition: ObjectItem.cpp:300
virtual void setPos(const QPointF &pos)
Definition: ObjectItem.cpp:79
const double & getLowerLeftX() const
It returns a constant reference to the x coordinate of the lower left corner.
Definition: Envelope.h:390
AbstractScene * getScene()
Definition: Context.cpp:61
ObjectItem(ItemController *controller=0, Observable *o=0)
Definition: ObjectItem.cpp:46
virtual te::gm::Coord2D getPosition()
Definition: ObjectItem.cpp:66
static Context * getInstance()
This function is called to create an instance of the class.
Definition: Context.cpp:46
double getZoomFactor()
Definition: Context.cpp:76
virtual bool contains(const QPointF &point) const
Definition: ObjectItem.cpp:418
double getHeight() const
It returns the envelope height.
Definition: Envelope.h:448
bool isValid() const
It tells if the rectangle is valid or not.
Definition: Envelope.h:438
virtual QRectF boundingRect() const
Definition: ObjectItem.cpp:167
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
Definition: ObjectItem.cpp:236
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
Definition: ObjectItem.cpp:241