Salome HOME
mergefrom branch BR_V511_PR tag mergeto_trunk_03feb09
[modules/yacs.git] / src / genericgui / SceneItem.cxx
1 //  Copyright (C) 2006-2008  CEA/DEN, EDF R&D
2 //
3 //  This library is free software; you can redistribute it and/or
4 //  modify it under the terms of the GNU Lesser General Public
5 //  License as published by the Free Software Foundation; either
6 //  version 2.1 of the License.
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 //  Lesser General Public License for more details.
12 //
13 //  You should have received a copy of the GNU Lesser General Public
14 //  License along with this library; if not, write to the Free Software
15 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 #include "SceneItem.hxx"
20 #include "Scene.hxx"
21 #include "SceneNodeItem.hxx"
22 #include "SceneHeaderNodeItem.hxx"
23 #include "SceneProcItem.hxx"
24 #include "SceneComposedNodeItem.hxx"
25 #include "GuiEditor.hxx"
26
27 #include "QtGuiContext.hxx"
28 #include "Menus.hxx"
29 #include <QGraphicsSceneHoverEvent>
30 #include <QPointF>
31
32 #include <cassert>
33 #include <cmath>
34
35 //#define _DEVDEBUG_
36 #include "YacsTrace.hxx"
37
38 using namespace std;
39 using namespace YACS::ENGINE;
40 using namespace YACS::HMI;
41
42 // ============================================================================
43
44 RootSceneItem::RootSceneItem(YACS::HMI::Subject *context)
45 {
46   _context=context;
47   _context->attach(this);
48 }
49
50 RootSceneItem::~RootSceneItem()
51 {
52 }
53
54 void RootSceneItem::update(GuiEvent event, int type, Subject* son)
55 {
56   DEBTRACE("RootSceneItem::update "<<eventName(event)<<" "<<type<<" "<<son);
57   GuiEditor *guiEditor = 0;
58   switch (event)
59     {
60     case YACS::HMI::NEWROOT:
61       setNewRoot(son);
62       break;
63     case YACS::HMI::ENDLOAD:
64       guiEditor = QtGuiContext::getQtCurrent()->getGMain()->_guiEditor;
65       GuiContext::getCurrent()->getSubjectProc()->select(true);
66       guiEditor->rebuildLinks();
67       break;
68     }
69 }
70
71 void RootSceneItem::setNewRoot(YACS::HMI::Subject *root)
72 {
73   DEBTRACE("RootSceneItem::setNewRoot");
74   _root = root;
75   QString name = _root->getName().c_str();
76   QGraphicsScene* scene = QtGuiContext::getQtCurrent()->getScene();
77   SceneProcItem *procItem = new SceneProcItem(scene, 0, name, root);
78   scene->addItem(procItem);
79   procItem->addHeader();
80 }
81
82 // ============================================================================
83
84 AbstractSceneItem::AbstractSceneItem(QGraphicsScene *scene, SceneItem *parent,
85                                      QString label)
86 {
87   _scene = dynamic_cast<Scene*>(scene);
88   _parent = parent;
89   _label = label;
90   _level = 1;
91   _margin = 4;
92   _nml = 5;
93   _width = 6;
94   _height = 4;
95   _penColor = QColor(0,0,128);
96   _hiPenColor = QColor(0,0,190);
97   _brushColor = QColor(128,128,128);
98   _hiBrushColor = QColor(190,190,190);
99   _hasHeader = false;
100   _hasNml= false;
101   _optimize = true; // to be set individually or globally by user (shrink items)
102   _dragable = false;
103   _dragButton = Qt::LeftButton;
104   if (_parent) 
105     _level = _parent->getLevel() +1;
106   DEBTRACE("AbstractSceneItem::AbstractSceneItem "<<label.toStdString()
107            <<" "<<this<<" "<<_parent<<" "<< _level); 
108 }
109
110 AbstractSceneItem::~AbstractSceneItem()
111 {
112 }
113
114 int AbstractSceneItem::getLevel()
115 {
116   return  _level;
117 }
118
119 qreal AbstractSceneItem::getMargin()
120 {
121   return  _margin;
122 }
123
124 void AbstractSceneItem::reorganize()
125 {
126 }
127
128 QString AbstractSceneItem::getLabel()
129 {
130   return _label;
131 }
132
133 void AbstractSceneItem::addHeader()
134 {
135 }
136
137 qreal AbstractSceneItem::getHeaderBottom()
138 {
139   return 0;
140 }
141 qreal AbstractSceneItem::getWidth()
142 {
143   return _width;
144 }
145
146 qreal AbstractSceneItem::getHeight()
147 {
148   return _height;
149 }
150
151 //! AbstractSceneItem cannot be resized (only ComposedNodeItem can)
152 void AbstractSceneItem::setWidth(qreal width)
153 {
154 }
155
156 //! AbstractSceneItem cannot be resized (only ComposedNodeItem can)
157 void AbstractSceneItem::setHeight(qreal height)
158 {
159 }
160
161 qreal AbstractSceneItem::getInternWidth()
162 {
163   return _width -2*_margin -2*_hasNml*_nml;
164 }
165
166 qreal AbstractSceneItem::getInternHeight()
167 {
168   return _height -2*_hasNml*_nml;
169 }
170
171 QRectF AbstractSceneItem::childBoundingRect(AbstractSceneItem *child) const
172 {
173   QGraphicsItem *item = dynamic_cast<QGraphicsItem*>(child);
174   assert(item);
175   return (item->mapToParent(item->boundingRect())).boundingRect();
176 }
177
178 void AbstractSceneItem::activateSelection(bool selected)
179 {
180   if (_parent) _parent->activateSelection(selected);
181 }
182
183 void AbstractSceneItem::setGeometryOptimization(bool optimize)
184 {
185   _optimize = optimize;
186 }
187 // ============================================================================
188
189 SceneItem::SceneItem(QGraphicsScene *scene, SceneItem *parent,
190                      QString label)
191   : QGraphicsItem(parent), AbstractSceneItem(scene, parent, label)
192 {
193   _hover = false;
194   setToolTip(_label);
195   DEBTRACE("SceneItem::SceneItem "<<label.toStdString()<<" "<<this<<" "<<_parent<<" "<< _level); 
196   setFlag(QGraphicsItem::ItemIsSelectable);
197   setAcceptsHoverEvents(true);
198 }
199
200 SceneItem::~SceneItem()
201 {
202 }
203
204 void SceneItem::setParent(SceneItem* parent)
205 {
206   setParentItem(parent);
207   _parent = parent;
208   if (_parent) 
209     _level = _parent->getLevel() +1;
210 }
211
212 QRectF SceneItem::boundingRect() const
213 {
214 //   DEBTRACE("SceneItem::boundingRect " <<_label.toStdString()
215 //            <<" "<<_width<<" "<< _height);
216   qreal penWidth = 1;
217   return QRectF(- penWidth/2, - penWidth/2,
218                 _width + penWidth/2, _height + penWidth/2);
219 }
220
221 QRectF SceneItem::childrenBoundingRect() const
222 {
223   return QGraphicsItem::childrenBoundingRect();
224 }
225
226 void SceneItem::paint(QPainter *painter,
227                       const QStyleOptionGraphicsItem *option,
228                       QWidget *widget)
229 {
230   //DEBTRACE("SceneItem::paint");
231   painter->save();
232   painter->setPen(getPenColor());
233   painter->setBrush(getBrushColor());
234   painter->drawRoundRect(QRectF(0, 0, _width, _height), 33*_height/_width, 33);
235   painter->restore();
236 }
237
238 void SceneItem::setTopLeft(QPointF topLeft)
239 {
240   setPos(topLeft);
241   if (_parent)
242     _parent->checkGeometryChange();
243 }
244
245 void SceneItem::checkGeometryChange()
246 {
247   QRectF childrenBox = childrenBoundingRect();
248   qreal newWidth = childrenBox.width() + 2*_margin;
249   qreal newHeight =  childrenBox.height() + 2*_margin;
250   SceneNodeItem *aNode = dynamic_cast<SceneNodeItem*>(this);
251   if (aNode)
252     {
253       newWidth  += 2*_nml;
254       newHeight += 2*_nml;
255     }
256   bool resize = false;
257   bool wider = (newWidth > _width + 0.5);
258   qreal deltaW = 0;
259   bool higher = (newHeight > _height + 0.5);
260   qreal deltaH = 0;
261   bool changeWidth = (fabs(newWidth - _width) > 0.5);
262
263   if (wider || (_optimize && (newWidth < _width)))
264     {
265       deltaW = newWidth - _width;
266       _width = newWidth;
267       resize = true;
268     }
269   if (higher || (_optimize && (newHeight < _height)))
270     {
271       deltaH = newHeight - _height;
272       _height = newHeight;
273       resize = true;
274     }
275 //   DEBTRACE("SceneItem::checkGeometryChange "<<_label.toStdString() <<
276 //            " " << wider << " " << higher << " " << changeWidth <<  " " << resize);
277   if (aNode)
278     {
279       if (changeWidth) aNode->adjustHeader();
280       if (wider || higher)
281         {
282           QPointF oldPos(pos().x() - deltaW, pos().y() - deltaH);
283           if (SceneComposedNodeItem *bloc = dynamic_cast<SceneComposedNodeItem*>(_parent))
284             bloc->collisionResolv(aNode, oldPos);
285         }  
286     }
287   if (resize)
288     { 
289 //       DEBTRACE("SceneItem::checkGeometryChange "<<_label.toStdString()<<" "<<_width<<" "<<_height);
290       prepareGeometryChange();
291       if (_parent)
292         _parent->checkGeometryChange();
293     }
294 }
295
296 // /*!
297 //  * When Zooming, filter all mouse events to items: 
298 //  * do not work, scene do not receive...
299 //  */
300 // bool SceneItem::sceneEvent(QEvent *event)
301 // {
302 //   if (_scene->isZooming())
303 //     return false;
304 //   else
305 //     return QGraphicsItem::sceneEvent(event);
306 // }
307
308 void SceneItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
309 {
310   DEBTRACE("SceneItem::mousePressEvent " << _label.toStdString()
311            << " " << acceptedMouseButtons () << " " << _scene->isZooming());
312   if (!_scene->isZooming()) activateSelection(true);
313 }
314
315 QColor SceneItem::getPenColor()
316 {
317   if (isSelected())
318     return _hiPenColor;
319   else 
320     return _penColor;
321 }
322
323 QColor SceneItem::hoverColor(QColor origColor)
324 {
325   qreal h, s, v, a;
326   origColor.getHsvF(&h, &s, &v, &a);
327   v = 0.95*v;
328   return QColor::fromHsvF(h, s, v, a);
329 }
330
331 void SceneItem::hoverEnterEvent(QGraphicsSceneHoverEvent * event)
332 {
333   _hover = true;
334   update();
335 }
336
337 void SceneItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event)
338 {
339 }
340
341 void SceneItem::hoverLeaveEvent(QGraphicsSceneHoverEvent * event)
342 {
343   _hover = false;
344   update();
345 }
346
347 QColor SceneItem::getBrushColor()
348 {
349   QColor color;
350   if (isSelected())
351     color = _hiBrushColor;
352   else 
353     color = _brushColor;
354   if (_hover)
355     color = hoverColor(color);
356   return color;
357 }
358
359 void SceneItem::popupMenu(QWidget *caller, const QPoint &globalPos)
360 {
361   MenusBase m;
362   m.popupMenu(caller, globalPos);
363 }
364