Salome HOME
mergefrom branch BR_V511_PR tag mergeto_trunk_03feb09
[modules/yacs.git] / src / genericgui / SceneNodeItem.cxx
diff --git a/src/genericgui/SceneNodeItem.cxx b/src/genericgui/SceneNodeItem.cxx
new file mode 100644 (file)
index 0000000..c0e1c47
--- /dev/null
@@ -0,0 +1,343 @@
+//  Copyright (C) 2006-2008  CEA/DEN, EDF R&D
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+#include "SceneNodeItem.hxx"
+#include "SceneComposedNodeItem.hxx"
+#include "SceneHeaderNodeItem.hxx"
+#include "SceneInPortItem.hxx"
+#include "SceneOutPortItem.hxx"
+#include "SceneCtrlInPortItem.hxx"
+#include "SceneCtrlOutPortItem.hxx"
+#include "Scene.hxx"
+#include "QtGuiContext.hxx"
+#include "Menus.hxx"
+
+#include "Switch.hxx"
+
+#include <QGraphicsSceneHoverEvent>
+#include <QPointF>
+
+#include <sstream>
+#include <cassert>
+
+//#define _DEVDEBUG_
+#include "YacsTrace.hxx"
+
+using namespace std;
+using namespace YACS::ENGINE;
+using namespace YACS::HMI;
+
+SceneNodeItem::SceneNodeItem(QGraphicsScene *scene, SceneItem *parent,
+                             QString label, Subject *subject)
+  : SceneObserverItem(scene, parent, label, subject)
+{
+  _inPorts.clear();
+  _outPorts.clear();
+  _header = 0;
+  _height = 50 + 2*_nml;
+  _width = 2*ScenePortItem::getPortWidth() + 3*_margin + 2*_nml;
+  _brushColor = QColor(0,0,128);
+  _moving = false;
+  _hasNml = true;
+  _dragable = true;
+  _dragButton = Qt::MidButton;
+  _execState = YACS::UNDEFINED;
+}
+
+SceneNodeItem::~SceneNodeItem()
+{
+  if (SceneComposedNodeItem* parent = getParent())
+    parent->removeChildFromList(this);
+}
+
+void SceneNodeItem::setWidth(qreal width)
+{
+  _width = width;
+  adjustHeader();
+}
+
+void SceneNodeItem::setHeight(qreal height)
+{
+  _height = height;
+}
+
+void SceneNodeItem::addHeader()
+{
+  DEBTRACE("SceneNodeItem::addHeader " << _label.toStdString());
+  if (!_hasHeader)
+    {
+      _hasHeader = true;
+      _header = new SceneHeaderNodeItem(_scene,
+                                        this,
+                                        getHeaderLabel());
+      updateState();
+      QPointF topLeft(_margin + _nml, _margin + _nml);
+      _header->setTopLeft(topLeft);
+      checkGeometryChange();
+    }
+}
+
+SceneHeaderItem* SceneNodeItem::getHeader()
+{
+  return _header;
+}
+
+void SceneNodeItem::paint(QPainter *painter,
+                          const QStyleOptionGraphicsItem *option,
+                          QWidget *widget)
+{
+  //DEBTRACE("SceneNodeItem::paint");
+  painter->save();
+  painter->setBrush(QBrush(Qt::NoBrush));
+  painter->setPen(QPen(Qt::NoPen));
+  painter->drawRect(QRectF(0, 0, _width, _height));
+
+  painter->setPen(getPenColor());
+  painter->setBrush(getBrushColor());
+  painter->drawRect(QRectF(_nml, _nml,
+                           _width-2*_nml, _height-2*_nml));
+  painter->restore();
+}
+
+void SceneNodeItem::update(GuiEvent event, int type, Subject* son)
+{
+  DEBTRACE("SceneNodeItem::update "<< eventName(event)<<" "<<type<<" "<<son);
+  SubjectNode *snode = 0;
+  Node *node = 0;
+  switch (event)
+    {
+    case YACS::HMI::RENAME:
+      DEBTRACE("SceneNodeItem::update RENAME " << _subject->getName());
+      updateName();
+      break;
+    case YACS::HMI::EDIT:
+      if (_header) _header->setEdited(type);
+      break;
+    case YACS::HMI::UPDATE:
+      updateState();
+      break;
+    case YACS::HMI::UPDATEPROGRESS:
+      setExecState(type);
+      break;
+    default:
+      ;
+    }
+}
+
+//! generic method to compute a graph for child nodes. implemented in some derived classes
+void SceneNodeItem::arrangeNodes(bool isRecursive)
+{
+}
+
+void SceneNodeItem::arrangeChildNodes()
+{
+}
+
+qreal SceneNodeItem::getHeaderBottom()
+{
+  qreal bottom = 0;
+  if (_hasHeader)
+    bottom = childBoundingRect(_header).bottom();
+  return bottom;
+}
+
+void SceneNodeItem::autoPosNewPort(AbstractSceneItem *item, int nbPorts)
+{
+  SceneInPortItem* inPortItem = dynamic_cast<SceneInPortItem*>(item);
+  bool isInPort = (inPortItem != 0);
+
+  qreal xLeft = _margin + _nml;
+  if (!isInPort) xLeft += ScenePortItem::getPortWidth() + _margin + _nml;
+
+  qreal yTop  = getHeaderBottom() + _margin;
+  yTop += nbPorts *(ScenePortItem::getPortHeight() + _margin);
+
+  DEBTRACE("left, top " << xLeft  << " " << yTop);
+  QPointF topLeft(xLeft, yTop);
+  item->setTopLeft(topLeft);
+}
+
+void SceneNodeItem::popupMenu(QWidget *caller, const QPoint &globalPos)
+{
+  NodeMenu m;
+  m.popupMenu(caller, globalPos);
+}
+
+SceneComposedNodeItem* SceneNodeItem::getParent()
+{
+  if (_parent)
+    return dynamic_cast<SceneComposedNodeItem*>(_parent);
+  else
+    return 0;
+}
+void SceneNodeItem::removeInPortFromList(AbstractSceneItem* inPort)
+{
+  _inPorts.remove(inPort);
+}
+
+void SceneNodeItem::removeOutPortFromList(AbstractSceneItem* outPort)
+{
+  _outPorts.remove(outPort);
+}
+
+void SceneNodeItem::setMoving(bool moving)
+{
+  //DEBTRACE("SceneNodeItem::setMoving " << _label.toStdString() << " " << moving);
+  _moving = moving;
+  SceneNodeItem *nodep = 0;
+  if (_parent && (nodep = dynamic_cast<SceneNodeItem*>(_parent)))
+    nodep->setMoving(false);
+}
+
+ScenePortItem* SceneNodeItem::getCtrlInPortItem()
+{
+  if (! _header) return 0;
+  return _header->getCtrlInPortItem();
+}
+
+ScenePortItem* SceneNodeItem::getCtrlOutPortItem()
+{
+  if (! _header) return 0;
+  return _header->getCtrlOutPortItem();
+}
+
+void SceneNodeItem::updateName()
+{
+  if (_header) _header->setText(getHeaderLabel());
+}
+
+QString SceneNodeItem::getMimeFormat()
+{
+  return "yacs/subjectNode";
+}
+
+void SceneNodeItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+  DEBTRACE("SceneNodeItem::mousePressEvent " << _label.toStdString());
+  SceneObserverItem::mousePressEvent(event);
+  if (!_scene->isZooming())
+    {
+      if (!_draging) setMoving(true);
+      _prevPos = pos();
+    }
+}
+
+void SceneNodeItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+  //DEBTRACE("SceneNodeItem::mouseReleaseEvent " << _label.toStdString());
+  SceneObserverItem::mouseReleaseEvent(event);
+  setMoving(false);
+  if ((pos() != _prevPos) && Scene::_autoComputeLinks)
+    {
+      YACS::HMI::SubjectProc* subproc = QtGuiContext::getQtCurrent()->getSubjectProc();
+      SceneItem *item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[subproc];
+      SceneComposedNodeItem *proc = dynamic_cast<SceneComposedNodeItem*>(item);
+      proc->rebuildLinks();
+    }
+}
+
+void SceneNodeItem::mouseMoveEvent(QGraphicsSceneMouseEvent * event)
+{
+  SceneObserverItem::mouseMoveEvent(event);
+  if (_moving)
+    {
+      if (SceneComposedNodeItem *bloc = dynamic_cast<SceneComposedNodeItem*>(_parent))
+        {
+          QPointF oldPos = pos();
+          QPointF aPos = oldPos + event->scenePos() - event->lastScenePos();
+          if (aPos.x() < _margin + _nml)
+            aPos.setX(_margin + _nml);
+          if (aPos.y() < _margin + bloc->getHeaderBottom() + _nml)
+            aPos.setY(_margin + bloc->getHeaderBottom() + _nml);
+          setTopLeft(aPos);
+          bloc->collisionResolv(this, oldPos);
+        }
+    }
+}
+
+void SceneNodeItem::setTopLeft(QPointF topLeft)
+{
+  QPointF oldPos = pos();
+  setPos(topLeft);
+  if (_parent)
+    {
+      if (SceneComposedNodeItem *bloc = dynamic_cast<SceneComposedNodeItem*>(_parent))
+        bloc->collisionResolv(this, oldPos);
+      _parent->checkGeometryChange();
+    }
+}
+
+void SceneNodeItem::adjustHeader()
+{
+  if (_header) _header->adjustGeometry();
+}
+
+ void SceneNodeItem::updateState()
+{
+  SubjectNode *snode = dynamic_cast<SubjectNode*>(_subject);
+  assert(snode);
+  Node *node = snode->getNode();
+  assert(node);
+  switch (node->getState())
+    {
+    case YACS::INVALID:
+      if (_header) _header->setValid(false);
+      break;
+    case YACS::READY:
+      if (_header) _header->setValid(true);
+      break;
+    default:
+      break;
+    }
+}
+
+void SceneNodeItem::setExecState(int execState)
+{
+  DEBTRACE("SceneNodeItem::setExecState " << execState);
+  _execState = execState;
+  if (_header) _header->setExecState(execState);
+}
+
+QString SceneNodeItem::getHeaderLabel()
+{
+  QString extLabel = _subject->getName().c_str();
+
+  SceneObserverItem *soi = 0;
+  SubjectSwitch* sswi = 0;
+
+  if ((_parent)
+      && (soi = dynamic_cast<SceneObserverItem*>(_parent))
+      && (sswi = dynamic_cast<SubjectSwitch*>(soi->getSubject())))
+    {
+      Switch *aswi = dynamic_cast<Switch*>(sswi->getNode());
+      SubjectNode *sno = dynamic_cast<SubjectNode*>(_subject);
+      int idcase = aswi->getRankOfNode(sno->getNode());
+      stringstream caseid;
+      if (idcase == Switch::ID_FOR_DEFAULT_NODE)
+        caseid << "default";
+      else
+        caseid << idcase;
+      extLabel += " (";
+      //extLabel += aswi->getCaseId(sno->getNode()).c_str();
+      extLabel += caseid.str().c_str();
+      extLabel += ")";
+      DEBTRACE(extLabel.toStdString());
+    }
+
+  return extLabel;
+}