Salome HOME
updated copyright message
[modules/yacs.git] / src / genericgui / SceneItem.cxx
1 // Copyright (C) 2006-2023  CEA, EDF
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, or (at your option) any later version.
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
20 #include "SceneItem.hxx"
21 #include "Scene.hxx"
22 #include "SceneNodeItem.hxx"
23 #include "SceneHeaderNodeItem.hxx"
24 #include "SceneProcItem.hxx"
25 #include "SceneElementaryNodeItem.hxx"
26 #include "SceneComposedNodeItem.hxx"
27 #include "GuiEditor.hxx"
28
29 #include "QtGuiContext.hxx"
30 #include "Menus.hxx"
31 #include <QGraphicsSceneHoverEvent>
32 #include <QPointF>
33
34 #include <cassert>
35 #include <cmath>
36
37 #include "Resource.hxx"
38
39 //#define _DEVDEBUG_
40 #include "YacsTrace.hxx"
41
42 using namespace std;
43 using namespace YACS::ENGINE;
44 using namespace YACS::HMI;
45
46 // ============================================================================
47
48 RootSceneItem::RootSceneItem(YACS::HMI::Subject *context)
49 {
50   _context=context;
51   _context->attach(this);
52 }
53
54 RootSceneItem::~RootSceneItem()
55 {
56 }
57
58 void RootSceneItem::update(GuiEvent event, int type, Subject* son)
59 {
60   DEBTRACE("RootSceneItem::update "<<eventName(event)<<" "<<type<<" "<<son);
61   GuiEditor *guiEditor = 0;
62   switch (event)
63     {
64     case YACS::HMI::NEWROOT:
65       setNewRoot(son);
66       break;
67     case YACS::HMI::ENDLOAD:
68       guiEditor = QtGuiContext::getQtCurrent()->getGMain()->_guiEditor;
69       GuiContext::getCurrent()->getSubjectProc()->select(true);
70       //guiEditor->rebuildLinks();
71       break;
72     }
73 }
74
75 void RootSceneItem::setNewRoot(YACS::HMI::Subject *root)
76 {
77   DEBTRACE("RootSceneItem::setNewRoot");
78   _root = root;
79   QString name = _root->getName().c_str();
80   QGraphicsScene* scene = QtGuiContext::getQtCurrent()->getScene();
81   SceneProcItem *procItem = new SceneProcItem(scene, 0, name, root);
82   scene->addItem(procItem);
83   procItem->addHeader();
84 }
85
86 // ============================================================================
87
88 AbstractSceneItem::AbstractSceneItem(QGraphicsScene *scene, SceneItem *parent,
89                                      QString label)
90 {
91   _scene = dynamic_cast<Scene*>(scene);
92   _parent = parent;
93   _label = label;
94   _level = 1;
95   _width = 6;
96   _height = 4;
97   _incHeight = 0; // used in elementaryNode when ports added
98   _penColor     = Resource::Scene_pen;
99   _hiPenColor   = Resource::Scene_hiPen;
100   _brushColor   = Resource::Scene_brush;
101   _hiBrushColor = Resource::Scene_hiBrush;
102   _hasHeader = false;
103   _optimize = true; // to be set individually or globally by user (shrink items)
104   _dragable = false;
105   _dragButton = Qt::LeftButton;
106   if (_parent) 
107     _level = _parent->getLevel() +1;
108   DEBTRACE("AbstractSceneItem::AbstractSceneItem "<<label.toStdString()
109            <<" "<<this<<" "<<_parent<<" "<< _level); 
110 }
111
112 AbstractSceneItem::~AbstractSceneItem()
113 {
114 }
115
116 int AbstractSceneItem::getLevel()
117 {
118   return  _level;
119 }
120
121 void AbstractSceneItem::setLevel()
122 {
123   if (_parent) 
124     _level = _parent->getLevel() +1;
125   if (SceneItem *item = dynamic_cast<SceneItem*>(this))
126     foreach (QGraphicsItem *child, item->childItems())
127       if (AbstractSceneItem *sci = dynamic_cast<AbstractSceneItem*>(child))
128         sci->setLevel();
129 }
130
131 void AbstractSceneItem::reorganize()
132 {
133 }
134
135 QString AbstractSceneItem::getLabel()
136 {
137   return _label;
138 }
139
140 void AbstractSceneItem::addHeader()
141 {
142 }
143
144 void AbstractSceneItem::addProgressItem()
145 {
146 }
147
148 qreal AbstractSceneItem::getHeaderBottom()
149 {
150   return 0;
151 }
152
153 qreal AbstractSceneItem::getWidth()
154 {
155   return _width;
156 }
157
158 qreal AbstractSceneItem::getHeight()
159 {
160   return _height;
161 }
162
163 //! AbstractSceneItem cannot be resized (only ComposedNodeItem can)
164 void AbstractSceneItem::setWidth(qreal width)
165 {
166 }
167
168 //! AbstractSceneItem cannot be resized (only ComposedNodeItem can)
169 void AbstractSceneItem::setHeight(qreal height)
170 {
171 }
172
173 QRectF AbstractSceneItem::childBoundingRect(AbstractSceneItem *child) const
174 {
175   QGraphicsItem *item = dynamic_cast<QGraphicsItem*>(child);
176   YASSERT(item);
177   return (item->mapToParent(item->boundingRect())).boundingRect();
178 }
179
180 void AbstractSceneItem::activateSelection(bool selected)
181 {
182   if (_parent) _parent->activateSelection(selected);
183 }
184
185 void AbstractSceneItem::setGeometryOptimization(bool optimize)
186 {
187   _optimize = optimize;
188 }
189 // ============================================================================
190
191 SceneItem::SceneItem(QGraphicsScene *scene, SceneItem *parent,
192                      QString label)
193   : QGraphicsItem(parent), AbstractSceneItem(scene, parent, label)
194 {
195   _hover = false;
196   _ancestorShrinked = false;
197   setToolTip(_label);
198   DEBTRACE("SceneItem::SceneItem "<<label.toStdString()<<" "<<this<<" "<<_parent<<" "<< _level); 
199   setFlag(QGraphicsItem::ItemIsSelectable);
200   setAcceptHoverEvents(true);
201 }
202
203 SceneItem::~SceneItem()
204 {
205 }
206
207 void SceneItem::setParent(SceneItem* parent)
208 {
209   setParentItem(parent);
210   _parent = parent;
211   if (_parent) 
212     _level = _parent->getLevel() +1;
213 }
214
215 QRectF SceneItem::boundingRect() const
216 {
217 //   DEBTRACE("SceneItem::boundingRect " <<_label.toStdString()
218 //            <<" "<<_width<<" "<< _height);
219   qreal penWidth = 1;
220   return QRectF(- penWidth/2, - penWidth/2,
221                 _width + penWidth/2, _height + penWidth/2);
222 }
223
224 QRectF SceneItem::childrenBoundingRect() const
225 {
226   return QGraphicsItem::childrenBoundingRect();
227 }
228
229 void SceneItem::paint(QPainter *painter,
230                       const QStyleOptionGraphicsItem *option,
231                       QWidget *widget)
232 {
233   //DEBTRACE("SceneItem::paint");
234 //   painter->save();
235 //   painter->setPen(getPenColor());
236 //   painter->setBrush(getBrushColor());
237 //   painter->drawRoundRect(QRectF(0, 0, _width, _height), 33*_height/_width, 33);
238 //   painter->restore();
239 }
240
241 void SceneItem::setTopLeft(QPointF topLeft)
242 {
243   setPos(int(topLeft.x()), int(topLeft.y()));
244   if (_parent)
245     _parent->checkGeometryChange();
246 }
247
248 void SceneItem::checkGeometryChange()
249 {
250   DEBTRACE("SceneItem::checkGeometryChange: enter : " << _label.toStdString() << " width= " << _width <<  " height= " << _height);
251   qreal newWidth;
252   qreal newHeight;
253   bool resize = false;
254   SceneElementaryNodeItem* aElemNode = dynamic_cast<SceneElementaryNodeItem*>(this);
255   if (QtGuiContext::getQtCurrent()->isLoadingPresentation())
256     {
257       newWidth  = _width;
258       newHeight = _height;
259       resize    = true;
260     }
261   else
262     {
263       if (aElemNode)
264         {
265           newWidth  = _width;
266           newHeight = _height;
267           resize    = true;
268           DEBTRACE("elementaryNode resize true");
269         }
270       else
271         {
272           QRectF childrenBox = childrenBoundingRect();
273           newWidth  = childrenBox.width();
274           newHeight = childrenBox.height();
275           DEBTRACE("composedNode newWidth= " << newWidth << " newHeight=" << newHeight);
276         }
277     }
278   bool wider = (newWidth > _width + 0.5);
279   qreal deltaW = 0;
280   bool higher = (newHeight > _height + 0.5);
281   qreal deltaH = 0;
282   bool changeWidth = (fabs(newWidth - _width) > 0.5);
283
284   if (wider || (_optimize && (newWidth < _width)))
285     {
286       deltaW = newWidth - _width;
287       resize = true;
288     }
289   if (higher || (_optimize && (newHeight < _height)))
290     {
291       deltaH = newHeight - _height;
292       resize = true;
293     }
294   if (_incHeight >0) //when a port has been added in an elementaryNode, force the collision resolv
295     {
296       higher = true;
297       deltaH = _incHeight;
298       resize = true;      
299     }
300   _incHeight = 0;
301   DEBTRACE("SceneItem::checkGeometryChange "<<_label.toStdString() <<
302            " " << wider << " " << higher << " " << changeWidth <<  " " << resize);
303
304   if (resize)
305     { 
306       prepareGeometryChange();
307       _width = newWidth;
308       _height = newHeight;
309     }
310   SceneNodeItem *aNode = dynamic_cast<SceneNodeItem*>(this);
311   if (aNode)
312     {
313       if (changeWidth) aNode->adjustHeader();
314       if (wider || higher)
315         {
316           QPointF oldPos(pos().x() - deltaW, pos().y() - deltaH);
317           if (SceneComposedNodeItem *bloc = dynamic_cast<SceneComposedNodeItem*>(_parent))
318             bloc->collisionResolv(aNode, oldPos);
319         }  
320       if (changeWidth) aNode->updateLinks();
321     }
322   if (resize)
323     { 
324       update();
325       if (_parent)
326         _parent->checkGeometryChange();
327     }
328   if(resize && aNode)
329       aNode->setExpandedWH();
330 }
331
332 /*! generic behaviour for headers:
333  *  obtain the tooltip from parent.
334  *  Method to be redefined in derived classes.
335  */
336 QString SceneItem::getToolTip()
337 {
338   QString tooltip = _label;
339   SceneItem *parent = getParent();
340   if (parent)
341     tooltip = parent->getToolTip();
342   return tooltip;
343 }
344
345 // /*!
346 //  * When Zooming, filter all mouse events to items: 
347 //  * do not work, scene do not receive...
348 //  */
349 // bool SceneItem::sceneEvent(QEvent *event)
350 // {
351 //   if (_scene->isZooming())
352 //     return false;
353 //   else
354 //     return QGraphicsItem::sceneEvent(event);
355 // }
356
357 void SceneItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
358 {
359   DEBTRACE("SceneItem::mousePressEvent " << _label.toStdString()
360            << " " << acceptedMouseButtons () << " " << _scene->isZooming());
361   if (!_scene->isZooming()) activateSelection(true);
362 }
363
364 QColor SceneItem::getPenColor()
365 {
366   if (isSelected())
367     return _hiPenColor;
368   else 
369     return _penColor;
370 }
371
372 QColor SceneItem::hoverColor(QColor origColor)
373 {
374   qreal r, g, b, a;
375   origColor.getRgbF(&r, &g, &b, &a);
376   r = 0.96*r;
377   g = 0.96*g;
378   b = 0.96*b;
379   return QColor::fromRgbF(r, g, b, a);
380
381    // qreal h, s, v, a;
382    // origColor.getHsvF(&h, &s, &v, &a);
383    // s = 1.05*s;
384    // if (s>254.0) s=255.0;
385    // return QColor::fromHsvF(h, s, v, a);
386 }
387
388 void SceneItem::hoverEnterEvent(QGraphicsSceneHoverEvent * event)
389 {
390   _hover = true;
391   update();
392 }
393
394 void SceneItem::hoverMoveEvent(QGraphicsSceneHoverEvent * event)
395 {
396 }
397
398 void SceneItem::hoverLeaveEvent(QGraphicsSceneHoverEvent * event)
399 {
400   _hover = false;
401   update();
402 }
403
404 QColor SceneItem::getBrushColor()
405 {
406   QColor color;
407   if (isSelected())
408     color = _hiBrushColor;
409   else 
410     color = _brushColor;
411   if (_hover)
412     color = hoverColor(color);
413   return color;
414 }
415
416 void SceneItem::popupMenu(QWidget *caller, const QPoint &globalPos)
417 {
418   MenusBase m;
419   m.popupMenu(caller, globalPos);
420 }
421
422 void SceneItem::setEventPos(QPointF point)
423 {
424   QPointF localPoint = mapFromScene(point);
425   if (localPoint.y() <= getHeaderBottom())
426     localPoint.setY(getHeaderBottom()+1);
427   _eventPos = localPoint;
428 }
429
430 void SceneItem::updateChildItems()
431 {
432 }
433
434 void SceneItem::shrinkExpandLink(bool se)
435 {
436 }
437
438
439 void SceneItem::shrinkExpandRecursive(bool isExpanding, bool fromHere, ShrinkMode theShrinkMode)
440 {
441 }
442
443 void SceneItem::updateLinks()
444 {
445 }