Salome HOME
8dfce3fae6d21516239be54fbe4a8b7b26fba477
[modules/yacs.git] / src / genericgui / SceneNodeItem.cxx
1 // Copyright (C) 2006-2020  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, 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 "SceneNodeItem.hxx"
21 #include "SceneComposedNodeItem.hxx"
22 #include "SceneProcItem.hxx"
23 #include "SceneHeaderNodeItem.hxx"
24 #include "SceneProgressItem.hxx"
25 #include "SceneInPortItem.hxx"
26 #include "SceneOutPortItem.hxx"
27 #include "SceneCtrlInPortItem.hxx"
28 #include "SceneCtrlOutPortItem.hxx"
29 #include "SceneLinkItem.hxx"
30 #include "Scene.hxx"
31 #include "QtGuiContext.hxx"
32 #include "Menus.hxx"
33 #include "GuiEditor.hxx"
34 #include "InPort.hxx"
35 #include "OutPort.hxx"
36
37 #include "Switch.hxx"
38 #include "Resource.hxx"
39
40 #include <QGraphicsSceneHoverEvent>
41 #include <QPointF>
42
43 #include <cmath>
44 #include <sstream>
45 #include <cassert>
46 #include <vector>
47
48 //#define _DEVDEBUG_
49 #include "YacsTrace.hxx"
50
51 using namespace std;
52 using namespace YACS::ENGINE;
53 using namespace YACS::HMI;
54
55 SceneNodeItem::SceneNodeItem(QGraphicsScene *scene, SceneItem *parent,
56                              QString label, Subject *subject)
57   : SceneObserverItem(scene, parent, label, subject)
58 {
59   _inPorts.clear();
60   _outPorts.clear();
61   _header = 0;
62   _progressItem = 0;
63   _brushColor = Resource::Scene_pen;
64   _moving = false;
65   _moved = false;
66   _blocX = false;
67   _blocY = false;
68   _dragable = true;
69   _dragButton = Qt::MidButton;
70   _execState = YACS::UNDEFINED;
71   _expanded = true;
72   _expandedPos = QPointF(0,0);
73   _expandedWidth = _width;
74   _expandedHeight = _height;
75   _shownState = expandShown;
76 }
77
78 SceneNodeItem::~SceneNodeItem()
79 {
80   if (SceneComposedNodeItem* parent = getParent())
81     parent->removeChildFromList(this);
82 }
83
84 void SceneNodeItem::setWidth(qreal width)
85 {
86   if (width != _width)
87     {
88       prepareGeometryChange();
89       _width = width;
90       _expandedWidth = _width;
91       adjustHeader();
92       QGraphicsItem::update();
93     }
94 }
95
96 void SceneNodeItem::setHeight(qreal height)
97 {
98   if (height != _height)
99     {
100       prepareGeometryChange();
101       _height = height;
102       _expandedHeight = _height;
103       QGraphicsItem::update();
104     }
105 }
106
107 void SceneNodeItem::addHeader()
108 {
109   DEBTRACE("SceneNodeItem::addHeader " << _label.toStdString());
110   if (!_hasHeader)
111     {
112       _hasHeader = true;
113       _header = new SceneHeaderNodeItem(_scene,
114                                         this,
115                                         getHeaderLabel());
116       updateState();
117       checkGeometryChange();
118     }
119 }
120
121 SceneHeaderItem* SceneNodeItem::getHeader()
122 {
123   return _header;
124 }
125
126 void SceneNodeItem::addProgressItem()
127 {
128   DEBTRACE("SceneNodeItem::addProgressItem ");
129   if (!_progressItem)
130     {
131       _progressItem = new SceneProgressItem(_scene,
132                                         this,
133                                         "progress");
134       _progressItem->setText("0");
135       updateState();
136       checkGeometryChange();
137     }
138 }
139
140 void SceneNodeItem::paint(QPainter *painter,
141                           const QStyleOptionGraphicsItem *option,
142                           QWidget *widget)
143 {
144   //DEBTRACE("SceneNodeItem::paint");
145 }
146
147 void SceneNodeItem::update(GuiEvent event, int type, Subject* son)
148 {
149   DEBTRACE("SceneNodeItem::update "<< eventName(event)<<" "<<type<<" "<<son);
150   SceneObserverItem::update(event, type, son);
151   SubjectNode *snode = 0;
152   Node *node = 0;
153   switch (event)
154     {
155     case YACS::HMI::RENAME:
156       DEBTRACE("SceneNodeItem::update RENAME " << _subject->getName());
157       updateName();
158       break;
159     case YACS::HMI::EDIT:
160       if (_header) _header->setEdited(type);
161       break;
162     case YACS::HMI::UPDATE:
163       updateState();
164       break;
165     case YACS::HMI::UPDATEPROGRESS:
166       setExecState(type);
167       break;
168     default:
169       ;
170     }
171 }
172
173 //! generic method to compute a graph for child nodes. implemented in some derived classes
174 void SceneNodeItem::arrangeNodes(bool isRecursive)
175 {
176 }
177
178 void SceneNodeItem::arrangeChildNodes()
179 {
180 }
181
182 void SceneNodeItem::reorganizeShrinkExpand(ShrinkMode theShrinkMode)
183 {
184 }
185
186 qreal SceneNodeItem::getHeaderBottom()
187 {
188   if (_hasHeader) {
189     return _header->getHeaderBottom();
190   } else {
191     return 0;
192   };
193 }
194
195 void SceneNodeItem::autoPosNewPort(AbstractSceneItem *item, int nbPorts) {
196 }
197
198 void SceneNodeItem::popupMenu(QWidget *caller, const QPoint &globalPos)
199 {
200   NodeMenu m;
201   m.popupMenu(caller, globalPos);
202 }
203
204 SceneComposedNodeItem* SceneNodeItem::getParent()
205 {
206   if (_parent)
207     return dynamic_cast<SceneComposedNodeItem*>(_parent);
208   else
209     return 0;
210 }
211 void SceneNodeItem::removeInPortFromList(AbstractSceneItem* inPort)
212 {
213   _inPorts.remove(inPort);
214 }
215
216 void SceneNodeItem::removeOutPortFromList(AbstractSceneItem* outPort)
217 {
218   _outPorts.remove(outPort);
219 }
220
221 void SceneNodeItem::setMoving(bool moving)
222 {
223   //DEBTRACE("SceneNodeItem::setMoving " << _label.toStdString() << " " << moving);
224   _moving = moving;
225   SceneNodeItem *nodep = 0;
226   if (_parent && (nodep = dynamic_cast<SceneNodeItem*>(_parent)))
227     nodep->setMoving(false);
228 }
229
230 ScenePortItem* SceneNodeItem::getCtrlInPortItem()
231 {
232   if (! _header) return 0;
233   return _header->getCtrlInPortItem();
234 }
235
236 ScenePortItem* SceneNodeItem::getCtrlOutPortItem()
237 {
238   if (! _header) return 0;
239   return _header->getCtrlOutPortItem();
240 }
241
242 void SceneNodeItem::updateName()
243 {
244   if (_header) _header->setText(getHeaderLabel());
245 }
246
247 QString SceneNodeItem::getMimeFormat()
248 {
249   return "yacs/subjectNode";
250 }
251
252 void SceneNodeItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
253 {
254   DEBTRACE("SceneNodeItem::mousePressEvent " << _label.toStdString());
255   SceneObserverItem::mousePressEvent(event);
256   if (!_scene->isZooming())
257     {
258       if (!_draging) setMoving(true);
259       _prevPos = pos();
260     }
261 }
262
263 void SceneNodeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
264 {
265   //DEBTRACE("SceneNodeItem::mouseReleaseEvent " << _label.toStdString());
266   SceneObserverItem::mouseReleaseEvent(event);
267   setMoving(false);
268   if ((pos() != _prevPos) && Scene::_autoComputeLinks)
269     {
270       YACS::HMI::SubjectProc* subproc = QtGuiContext::getQtCurrent()->getSubjectProc();
271       SceneItem *item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[subproc];
272       SceneComposedNodeItem *proc = dynamic_cast<SceneComposedNodeItem*>(item);
273       proc->rebuildLinks();
274     }
275   if (_moved)
276     if (Resource::ensureVisibleWhenMoved)
277       QtGuiContext::getQtCurrent()->getView()->ensureVisible(this);
278   _moved = false;
279 }
280
281 void SceneNodeItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
282 {
283   SceneObserverItem::mouseMoveEvent(event);
284   if (_moving)
285     {
286       if (SceneComposedNodeItem *bloc = dynamic_cast<SceneComposedNodeItem*>(_parent))
287         {
288           QPointF oldPos = pos();
289           QPointF aPos = oldPos + event->scenePos() - event->lastScenePos();
290           if (aPos != oldPos)
291             _moved = true;
292           if (aPos.x() > oldPos.x()) _blocX = false;
293           if (aPos.y() > oldPos.y()) _blocY = false;
294           if (aPos.x() < Resource::Border_Margin)
295             {
296               aPos.setX(Resource::Border_Margin);
297               _blocX = true;
298             }
299           if ( aPos.y() < bloc->getHeaderBottom() )
300             {
301               aPos.setY(bloc->getHeaderBottom());
302               _blocY = true;
303             }
304           setTopLeft(aPos);
305           bloc->collisionResolv(this, oldPos);
306         }
307     }
308 }
309
310 void SceneNodeItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
311 {
312   DEBTRACE("SceneNodeItem::mouseDoubleClickEvent");
313   QtGuiContext::getQtCurrent()->getGMain()->_guiEditor->shrinkExpand(QApplication::keyboardModifiers());
314 }
315
316 void SceneNodeItem::setTopLeft(QPointF topLeft)
317 {
318   if (_shownState == shrinkHidden) {
319     _expandedPos = topLeft;
320     return;
321   }
322   QPointF oldPos = pos();
323   setPos(topLeft);
324
325   //update links
326   updateLinks();
327
328   if (_parent)
329     {
330       if (SceneComposedNodeItem *bloc = dynamic_cast<SceneComposedNodeItem*>(_parent))
331         bloc->collisionResolv(this, oldPos);
332       _parent->checkGeometryChange();
333     }
334   _expandedPos = pos();
335 }
336
337 void SceneNodeItem::adjustHeader()
338 {
339   if (_header) _header->adjustGeometry();
340 }
341
342  void SceneNodeItem::updateState()
343 {
344   SubjectNode *snode = dynamic_cast<SubjectNode*>(_subject);
345   YASSERT(snode);
346   Node *node = snode->getNode();
347   YASSERT(node);
348   switch (node->getState())
349     {
350     case YACS::INVALID:
351       if (_header) _header->setValid(false);
352       break;
353     case YACS::READY:
354       if (_header) _header->setValid(true);
355       break;
356     default:
357       break;
358     }
359 }
360
361 void SceneNodeItem::setExecState(int execState)
362 {
363   DEBTRACE("SceneNodeItem::setExecState " << execState);
364   _execState = execState;
365   if (_header) _header->setExecState(execState);
366 }
367
368 QString SceneNodeItem::getHeaderLabel()
369 {
370   DEBTRACE("SceneNodeItem::getHeaderLabel");
371   QString extLabel = _subject->getName().c_str();
372
373   SceneObserverItem *soi = 0;
374   SubjectSwitch* sswi = 0;
375
376   if ((_parent)
377       && (soi = dynamic_cast<SceneObserverItem*>(_parent))
378       && (sswi = dynamic_cast<SubjectSwitch*>(soi->getSubject())))
379     {
380       Switch *aswi = dynamic_cast<Switch*>(sswi->getNode());
381       SubjectNode *sno = dynamic_cast<SubjectNode*>(_subject);
382       int idcase = aswi->getRankOfNode(sno->getNode());
383       stringstream caseid;
384       if (idcase == Switch::ID_FOR_DEFAULT_NODE)
385         caseid << "default";
386       else
387         caseid << idcase;
388       extLabel += " (";
389       //extLabel += aswi->getCaseId(sno->getNode()).c_str();
390       extLabel += caseid.str().c_str();
391       extLabel += ")";
392       DEBTRACE(extLabel.toStdString());
393     }
394
395   return extLabel;
396 }
397
398 void SceneNodeItem::updateLinks()
399 {
400   //update control links
401   std::list<SubjectControlLink*> lscl=dynamic_cast<SubjectNode*>(_subject)->getSubjectControlLinks();
402   for (std::list<SubjectControlLink*>::const_iterator it = lscl.begin(); it != lscl.end(); ++it)
403     {
404       SceneLinkItem* item = dynamic_cast<SceneLinkItem*>(QtGuiContext::getQtCurrent()->_mapOfSceneItem[*it]);
405       item->updateShape();
406     }
407
408   //update data links through child items update (SceneDataPortItem)
409   updateChildItems();
410 }
411
412 void SceneNodeItem::updateChildItems()
413 {
414   foreach (QGraphicsItem *child, childItems())
415     {
416       if (SceneItem *sci = dynamic_cast<SceneItem*>(child))
417         {
418            sci->updateLinks();
419         }
420     }
421 }
422
423 void SceneNodeItem::shrinkExpandLink(bool se)
424 {
425   foreach (QGraphicsItem *child, childItems())
426     {
427       if (SceneItem *sci = dynamic_cast<SceneItem*>(child))
428         {
429            sci->shrinkExpandLink(se);
430         }
431     }
432 }
433
434 void SceneNodeItem::showOutScopeLinks()
435 {
436   SubjectNode *snode = dynamic_cast<SubjectNode*>(_subject);
437   YASSERT(snode);
438   Node *node = snode->getNode();
439   YASSERT(node);
440   vector<pair<OutPort *, InPort *> > listLeaving  = node->getSetOfLinksLeavingCurrentScope();
441   vector<pair<InPort *, OutPort *> > listIncoming = node->getSetOfLinksComingInCurrentScope();
442   vector<pair<OutPort *, InPort *> > outScope = listLeaving;
443   vector<pair<InPort *, OutPort *> >::iterator it1;
444   for (it1 = listIncoming.begin(); it1 != listIncoming.end(); ++it1)
445     {
446       pair<OutPort *, InPort *> outin = pair<OutPort *, InPort *>((*it1).second, (*it1).first);
447       outScope.push_back(outin);
448     }
449   vector<pair<OutPort*, InPort*> >::const_iterator it = outScope.begin();
450   for( ; it != outScope.end(); ++it)
451   {
452     YASSERT(QtGuiContext::getQtCurrent()->_mapOfSubjectLink.count(*it));
453     SubjectLink* slink = QtGuiContext::getQtCurrent()->_mapOfSubjectLink[*it];
454     YASSERT(QtGuiContext::getQtCurrent()->_mapOfSceneItem.count(slink));
455     SceneItem *item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[slink];
456     item->show();
457   }
458 }
459
460 void SceneNodeItem::setShownState(shownState ss)
461 {
462   _shownState = ss;
463 }
464
465 bool SceneNodeItem::hasProgressBar() const
466 {
467   return _progressItem != 0;
468 }