1 // Copyright (C) 2006-2008 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #include "SceneBlocItem.hxx"
20 #include "SceneComposedNodeItem.hxx"
21 #include "SceneElementaryNodeItem.hxx"
22 #include "SceneHeaderItem.hxx"
23 #include "SceneHeaderNodeItem.hxx"
24 #include "SceneInPortItem.hxx"
25 #include "SceneOutPortItem.hxx"
26 #include "SceneLinkItem.hxx"
27 #include "SceneCtrlLinkItem.hxx"
28 #include "LinkMatrix.hxx"
29 #include "LinkAStar.hxx"
30 #include "ItemMimeData.hxx"
31 #include "QtGuiContext.hxx"
33 #include "Message.hxx"
34 #include "guiObservers.hxx"
35 #include "GuiEditor.hxx"
40 #include <QGraphicsSceneDragDropEvent>
45 #include "YacsTrace.hxx"
48 using namespace YACS::ENGINE;
49 using namespace YACS::HMI;
51 SceneComposedNodeItem::SceneComposedNodeItem(QGraphicsScene *scene, SceneItem *parent,
52 QString label, Subject *subject)
53 : SceneNodeItem(scene, parent, label, subject)
55 DEBTRACE("SceneComposedNodeItem::SceneComposedNodeItem " <<label.toStdString());
56 _brushColor = QColor(213,213,213);
57 _hiBrushColor = QColor(225,225,225);
58 _penColor = QColor(120,120,120);
59 _hiPenColor = QColor( 60, 60, 60);
64 SceneComposedNodeItem::~SceneComposedNodeItem()
68 QRectF SceneComposedNodeItem::childrenBoundingRect() const
70 QRectF ChildrenBRect =QRectF(x(), y(), 5, 5);
71 if (_header) ChildrenBRect = _header->getMinimalBoundingRect();
72 for (list<AbstractSceneItem*>::const_iterator it=_children.begin(); it!=_children.end(); ++it)
73 ChildrenBRect = ChildrenBRect.united(childBoundingRect(*it));
77 void SceneComposedNodeItem::paint(QPainter *painter,
78 const QStyleOptionGraphicsItem *option,
81 //DEBTRACE("SceneComposedNodeItem::paint " << _label.toStdString());
83 painter->setBrush(QBrush(Qt::NoBrush));
84 painter->setPen(QPen(Qt::NoPen));
85 painter->drawRect(QRectF(0, 0, _width, _height));
86 painter->setPen(getPenColor());
87 painter->setBrush(getBrushColor());
88 painter->drawRect(QRectF(_nml, _nml,
89 _width-2*_nml, _height-2*_nml));
93 void SceneComposedNodeItem::update(GuiEvent event, int type, Subject* son)
95 DEBTRACE("SceneComposedNodeItem::update "<< eventName(event)<<" "<<type<<" "<<son);
96 SceneNodeItem::update(event, type, son);
97 AbstractSceneItem *item;
103 case YACS::HMI::BLOC:
104 item = new SceneBlocItem(_scene,
106 son->getName().c_str(),
109 autoPosNewChild(item, _children, true);
111 case YACS::HMI::FORLOOP:
112 case YACS::HMI::WHILELOOP:
113 case YACS::HMI::SWITCH:
114 case YACS::HMI::FOREACHLOOP:
115 case YACS::HMI::OPTIMIZERLOOP:
116 item = new SceneComposedNodeItem(_scene,
118 son->getName().c_str(),
121 autoPosNewChild(item, _children, true);
123 case YACS::HMI::PYTHONNODE:
124 case YACS::HMI::PYFUNCNODE:
125 case YACS::HMI::CORBANODE:
126 case YACS::HMI::CPPNODE:
127 case YACS::HMI::SALOMENODE:
128 case YACS::HMI::SALOMEPYTHONNODE:
129 case YACS::HMI::XMLNODE:
130 case YACS::HMI::PRESETNODE:
131 case YACS::HMI::OUTNODE:
132 case YACS::HMI::STUDYINNODE:
133 case YACS::HMI::STUDYOUTNODE:
134 item = new SceneElementaryNodeItem(_scene,
136 son->getName().c_str(),
139 autoPosNewChild(item, _children, true);
141 case YACS::HMI::INPUTPORT:
142 case YACS::HMI::INPUTDATASTREAMPORT:
143 item = new SceneInPortItem(_scene,
145 son->getName().c_str(),
147 _header->autoPosNewPort(item);
148 _inPorts.push_back(item);
150 case YACS::HMI::OUTPUTPORT:
151 case YACS::HMI::OUTPUTDATASTREAMPORT:
152 item = new SceneOutPortItem(_scene,
154 son->getName().c_str(),
156 _header->autoPosNewPort(item);
157 _outPorts.push_back(item);
160 DEBTRACE("SceneComposedNodeItem::update() ADD, type not handled:" << type);
163 case YACS::HMI::ADDLINK:
166 case YACS::HMI::DATALINK:
167 if (SubjectLink* slink = dynamic_cast<SubjectLink*>(son))
169 SubjectDataPort* soutp = slink->getSubjectOutPort();
170 SubjectDataPort* sinp = slink->getSubjectInPort();
171 SceneItem * scout = QtGuiContext::getQtCurrent()->_mapOfSceneItem[soutp];
172 SceneItem * scin = QtGuiContext::getQtCurrent()->_mapOfSceneItem[sinp];
173 ScenePortItem* from = dynamic_cast<ScenePortItem*>(scout);
174 ScenePortItem* to = dynamic_cast<ScenePortItem*>(scin);
175 item = new SceneLinkItem(_scene,
178 son->getName().c_str(),
184 case YACS::HMI::ADDCONTROLLINK:
187 case YACS::HMI::CONTROLLINK:
188 if (SubjectControlLink* slink = dynamic_cast<SubjectControlLink*>(son))
190 SubjectNode* soutn = slink->getSubjectOutNode();
191 SubjectNode* sinn = slink->getSubjectInNode();
192 SceneItem * scout = QtGuiContext::getQtCurrent()->_mapOfSceneItem[soutn];
193 SceneItem * scin = QtGuiContext::getQtCurrent()->_mapOfSceneItem[sinn];
194 SceneNodeItem* nodefrom = dynamic_cast<SceneNodeItem*>(scout);
195 SceneNodeItem* nodeto = dynamic_cast<SceneNodeItem*>(scin);
196 if (!nodeto || !nodefrom) DEBTRACE("CONTROLLINK problem -----------------");
197 ScenePortItem* from = nodefrom->getCtrlOutPortItem();
198 ScenePortItem* to = nodeto->getCtrlInPortItem();
199 if (!to || !from) DEBTRACE("CONTROLLINK problem -----------------");
200 item = new SceneCtrlLinkItem(_scene,
203 son->getName().c_str(),
209 case YACS::HMI::REMOVE:
210 //SceneObserverItem::update(event, type, son);
213 case YACS::HMI::SETCASE:
215 SubjectSwitch *sSwitch = dynamic_cast<SubjectSwitch*>(_subject);
218 Switch *aSwitch = dynamic_cast<Switch*>(sSwitch->getNode());
219 Node *node = aSwitch->edGetNode(type);
222 if (GuiContext::getCurrent()->_mapOfSubjectNode.count(node))
224 Subject* sub = GuiContext::getCurrent()->_mapOfSubjectNode[node];
225 if (QtGuiContext::getQtCurrent()->_mapOfSceneItem.count(sub))
227 SceneItem* item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[sub];
228 SceneNodeItem *scnode = dynamic_cast<SceneNodeItem*>(item);
229 if (scnode) scnode->updateName();
238 SceneItem * sinode = QtGuiContext::getQtCurrent()->_mapOfSceneItem[son];
239 removeChildFromList(sinode);
242 case YACS::HMI::PASTE:
244 SceneItem * sinode = QtGuiContext::getQtCurrent()->_mapOfSceneItem[son];
245 sinode->setParent(this);
246 autoPosNewChild(sinode, _children, true);
251 // DEBTRACE("SceneComposedNodeItem::update(), event not handled: "<< eventName(event));
255 void SceneComposedNodeItem::autoPosNewChild(AbstractSceneItem *item,
256 const std::list<AbstractSceneItem*> alreadySet,
260 qreal xLeft = _margin + _nml;
261 qreal yTop = getHeaderBottom() + _margin + _nml;
262 for (list<AbstractSceneItem*>::const_iterator it=alreadySet.begin(); it!=alreadySet.end(); ++it)
264 childrenBox = childrenBox.united(childBoundingRect(*it));
265 DEBTRACE((*it)->getLabel().toStdString());
266 DEBTRACE("childrenBox valid " << childrenBox.right() << " " << childrenBox.bottom());
268 if (childrenBox.isValid())
269 xLeft += childrenBox.right();
270 DEBTRACE("left, top " << xLeft << " " << yTop);
271 QPointF topLeft(xLeft, yTop);
272 if (isNew) _children.push_back(item);
273 item->setTopLeft(topLeft);
276 void SceneComposedNodeItem::popupMenu(QWidget *caller, const QPoint &globalPos)
279 m.popupMenu(caller, globalPos);
282 std::list<AbstractSceneItem*> SceneComposedNodeItem::getChildren()
287 void SceneComposedNodeItem::removeChildFromList(AbstractSceneItem* child)
289 _children.remove(child);
292 void SceneComposedNodeItem::reorganize()
294 DEBTRACE("SceneComposedNodeItem::reorganize() " << _label.toStdString());
295 list<AbstractSceneItem*> alreadySet;
296 for (list<AbstractSceneItem*>::const_iterator it=_children.begin(); it!=_children.end(); ++it)
298 autoPosNewChild(*it, alreadySet);
299 alreadySet.push_back(*it);
303 void SceneComposedNodeItem::collisionResolv(SceneItem* child, QPointF oldPos)
305 //DEBTRACE("SceneComposedNodeItem::collisionResolv " << _label.toStdString());
306 for (list<AbstractSceneItem*>::const_iterator it=_children.begin(); it!=_children.end(); ++it)
308 SceneNodeItem *other = dynamic_cast<SceneNodeItem*>(*it);
309 if (other && (other != child))
311 if (child->collidesWithItem(other))
313 //DEBTRACE("collision detected with " << other->getLabel().toStdString());
314 QRectF otherBR = (other->mapToParent(other->boundingRect())).boundingRect();
315 //oldPos = mapFromScene(oldPos);
316 qreal oldX = oldPos.x();
317 qreal oldY = oldPos.y();
318 qreal newX = child->pos().x();
319 qreal newY = child->pos().y();
320 qreal othX = otherBR.left()+0.5;
321 qreal othY = otherBR.top()+0.5;
322 //DEBTRACE("oldX=" << oldX << " oldY=" << oldY << " newX=" << newX << " newY=" << newY);
323 //DEBTRACE("otherLeft=" << otherBR.left() << " otherRight=" << otherBR.right() <<
324 // " otherTop=" << otherBR.top() << " otherBottom=" << otherBR.bottom());
325 //DEBTRACE("width=" << child->boundingRect().width() <<
326 // " height=" << child->boundingRect().height());
327 bool fromTop = (((oldY + child->boundingRect().height()) <= otherBR.top()+1) &&
328 ((newY + child->boundingRect().height()) >= otherBR.top()));
329 bool fromBottom = (( oldY >= otherBR.bottom()) &&
330 ( newY <= otherBR.bottom()));
331 bool fromRight = (( oldX >= otherBR.right()) &&
332 ( newX <= otherBR.right()));
333 bool fromLeft = (((oldX+ child->boundingRect().width()) <= otherBR.left()+1) &&
334 ((newX+ child->boundingRect().width()) >= otherBR.left()));
335 //DEBTRACE("fromTop=" << fromTop << " fromBottom=" << fromBottom
336 // << " fromRight=" << fromRight << " fromLeft=" << fromLeft);
337 bool pushOther =false;
338 bool blocThis = false;
341 //newY = otherBR.top() - child->boundingRect().height() -_margin;
342 othY = newY + child->boundingRect().height();
347 //newX = otherBR.left() -child->boundingRect().width() - _margin;
348 othX = newX+ child->boundingRect().width();
353 newY = otherBR.bottom() + 1;
358 newX = otherBR.right()+ 1;
361 //DEBTRACE("newX=" << newX << " newY=" << newY);
362 if (blocThis) child->setTopLeft(QPointF(newX, newY));
365 other->setTopLeft(QPointF(othX, othY));
372 void SceneComposedNodeItem::rebuildLinks()
374 LinkMatrix matrix(this);
376 list<linkdef> alist = matrix.getListOfDataLinkDef();
377 list<linkdef> blist = matrix.getListOfCtrlLinkDef(); // add list operator ?
378 for (list<linkdef>::const_iterator ii = blist.begin(); ii != blist.end(); ++ii)
379 alist.push_back(*ii);
381 LinkAStar astar(matrix);
382 for (list<linkdef>::const_iterator it = alist.begin(); it != alist.end(); ++it)
385 // DEBTRACE("from("<<ali.from.first<<","<<ali.from.second
386 // <<") to ("<<ali.to.first<<","<<ali.to.second
387 // <<") " << ali.item->getLabel().toStdString());
388 bool isPath = astar.computePath(LNode(ali.from), LNode(ali.to));
389 if (! isPath) DEBTRACE("Link Path not found !");
390 LinkPath apath = matrix.getPath(astar.givePath());
391 // DEBTRACE(apath.size());
392 ali.item->setPath(apath);
397 void SceneComposedNodeItem::arrangeNodes(bool isRecursive)
399 DEBTRACE("SceneComposedItem::arrangeNodes " << isRecursive);
401 SubjectComposedNode *scnode = dynamic_cast<SubjectComposedNode*>(getSubject());
403 ComposedNode *cnode = dynamic_cast<ComposedNode*>(scnode->getNode());
408 list<Node*> children = cnode->edGetDirectDescendants();
409 for (list<Node*>::iterator it = children.begin(); it != children.end(); ++it)
411 DEBTRACE("child " << (*it)->getName());
412 SceneComposedNodeItem *scni = 0;
413 ComposedNode *cchild = dynamic_cast<ComposedNode*>(*it);
416 SubjectNode* sn = GuiContext::getCurrent()->_mapOfSubjectNode[cchild];
417 SceneItem* sci = QtGuiContext::getQtCurrent()->_mapOfSceneItem[sn];
418 if (sci) scni = dynamic_cast<SceneComposedNodeItem*>(sci);
422 DEBTRACE("call arrangeNode on child " << (*it)->getName());
423 scni->arrangeNodes(isRecursive);
432 void SceneComposedNodeItem::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
434 bool accepted = false;
435 const ItemMimeData *myData = dynamic_cast<const ItemMimeData*>(event->mimeData());
438 if (myData->hasFormat("yacs/cataService") ||
439 myData->hasFormat("yacs/cataNode") ||
440 myData->hasFormat("yacs/subjectNode"))
442 event->setAccepted(true);
444 QGraphicsItem::update();
448 event->setAccepted(accepted);
451 void SceneComposedNodeItem::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
455 QGraphicsItem::update();
458 void SceneComposedNodeItem::dropEvent(QGraphicsSceneDragDropEvent *event)
462 QGraphicsItem::update();
464 const ItemMimeData *myData = dynamic_cast<const ItemMimeData*>(event->mimeData());
466 if (myData->hasFormat("yacs/cataService") || myData->hasFormat("yacs/cataNode"))
468 SubjectComposedNode *cnode = dynamic_cast<SubjectComposedNode*>(getSubject());
469 QtGuiContext::getQtCurrent()->getGMain()->_guiEditor->CreateNodeFromCatalog(myData, cnode);
471 else if(myData->hasFormat("yacs/subjectNode"))
473 Subject *sub = myData->getSubject();
475 SubjectNode *node = dynamic_cast<SubjectNode*>(sub);
477 SubjectComposedNode *cnode = dynamic_cast<SubjectComposedNode*>(getSubject());
479 if (node->reparent(cnode))
484 QColor SceneComposedNodeItem::getPenColor()
487 return QColor(255,0,0);
494 QColor SceneComposedNodeItem::getBrushColor()
497 return _hiBrushColor;
501 color = _hiBrushColor;
506 color = hoverColor(color);