Salome HOME
Copyright update 2022
[modules/yacs.git] / src / genericgui / SceneElementaryNodeItem.cxx
1 // Copyright (C) 2006-2022  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 "SceneElementaryNodeItem.hxx"
21 #include "SceneInPortItem.hxx"
22 #include "SceneOutPortItem.hxx"
23 #include "SceneComposedNodeItem.hxx"
24 #include "guiObservers.hxx"
25 #include "commandsProc.hxx"
26 #include "Scene.hxx"
27 #include "ElementaryNode.hxx"
28 #include "InputPort.hxx"
29 #include "OutputPort.hxx"
30
31 #include "QtGuiContext.hxx"
32 #include "Menus.hxx"
33
34 #include "Resource.hxx"
35
36 #include <cassert>
37
38 //#define _DEVDEBUG_
39 #include "YacsTrace.hxx"
40
41 using namespace std;
42 using namespace YACS::ENGINE;
43 using namespace YACS::HMI;
44
45 SceneElementaryNodeItem::SceneElementaryNodeItem(QGraphicsScene *scene, SceneItem *parent,
46                                              QString label, Subject *subject)
47   : SceneNodeItem(scene, parent, label, subject)
48 {
49   _maxPorts = 0;
50   _width  = 2*Resource::Corner_Margin + 2*Resource::DataPort_Width + Resource::Space_Margin;
51   _height = Resource::Header_Height + Resource::Border_Margin;
52
53   _brushColor   = Resource::ElementaryNode_brush;
54   _hiBrushColor = Resource::ElementaryNode_hiBrush;
55   _penColor     = Resource::ElementaryNode_pen;
56   _hiPenColor   = Resource::ElementaryNode_hiPen;
57 }
58
59 SceneElementaryNodeItem::~SceneElementaryNodeItem()
60 {
61 }
62
63 //! SceneElementaryNodeItem cannot be resized (only ComposedNodeItem can)
64 void SceneElementaryNodeItem::setWidth(qreal width)
65 {
66 }
67
68 //! SceneElementaryNodeItem cannot be resized (only ComposedNodeItem can)
69 void SceneElementaryNodeItem::setHeight(qreal height)
70 {
71 }
72
73 void SceneElementaryNodeItem::paint(QPainter *painter,
74                           const QStyleOptionGraphicsItem *option,
75                           QWidget *widget)
76 {
77   //DEBTRACE("SceneElementaryNodeItem::paint");
78   painter->save();
79   QPen pen(getPenColor());
80   pen.setWidth(Resource::Thickness);
81   painter->setPen(pen);
82   painter->setBrush(getBrushColor());
83   int w = _width  - 2*Resource::Border_Margin;
84   int h = _height - 2*Resource::Border_Margin;
85   painter->drawRect(QRectF(Resource::Border_Margin, Resource::Border_Margin, w, h));
86   painter->restore();
87 }
88
89 void SceneElementaryNodeItem::update(GuiEvent event, int type, Subject* son)
90 {
91   DEBTRACE("SceneElementaryNodeItem::update "<< eventName(event)<<" "<<type<<" "<<son);
92   SceneNodeItem::update(event, type, son);
93   SceneItem *item;
94   switch (event)
95     {
96     case YACS::HMI::ADD:
97       switch (type)
98         {
99         case YACS::HMI::INPUTPORT:
100         case YACS::HMI::INPUTDATASTREAMPORT:
101           item =  new SceneInPortItem(_scene,
102                                       this,
103                                       son->getName().c_str(),
104                                       son);
105           autoPosNewPort(item, _inPorts.size());
106           _inPorts.push_back(item);
107           if (Scene::_autoComputeLinks && !QtGuiContext::getQtCurrent()->isLoading())
108             {
109               YACS::HMI::SubjectProc* subproc = QtGuiContext::getQtCurrent()->getSubjectProc();
110               SceneItem *item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[subproc];
111               SceneComposedNodeItem *proc = dynamic_cast<SceneComposedNodeItem*>(item);
112               proc->rebuildLinks();
113             }
114           break;
115         case YACS::HMI::OUTPUTPORT:
116         case YACS::HMI::OUTPUTDATASTREAMPORT:
117           item =  new SceneOutPortItem(_scene,
118                                        this,
119                                        son->getName().c_str(),
120                                        son);
121           autoPosNewPort(item, _outPorts.size());
122           _outPorts.push_back(item);
123           if (Scene::_autoComputeLinks && !QtGuiContext::getQtCurrent()->isLoading())
124             {
125               YACS::HMI::SubjectProc* subproc = QtGuiContext::getQtCurrent()->getSubjectProc();
126               SceneItem *item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[subproc];
127               SceneComposedNodeItem *proc = dynamic_cast<SceneComposedNodeItem*>(item);
128               proc->rebuildLinks();
129             }
130            break;
131 //         default:
132 //           DEBTRACE("SceneElementaryNodeItem::update() ADD, type not handled:" << type);
133         }
134       break;
135     case YACS::HMI::REMOVE:
136     case YACS::HMI::SYNCHRO:
137       reorganize();
138       break;
139 //     default:
140 //       DEBTRACE("SceneElementaryNodeItem::update(), event not handled:" << eventName(event));
141     }
142 }
143
144 void SceneElementaryNodeItem::autoPosNewPort(AbstractSceneItem *item, int nbPorts) {
145   DEBTRACE("SceneElementaryNodeItem::autoPosNewPort "<< _label.toStdString());
146   SceneInPortItem*   inPortItem = dynamic_cast<SceneInPortItem*>(item);
147   SceneOutPortItem* outPortItem = dynamic_cast<SceneOutPortItem*>(item);
148
149   bool toShow = (_shownState == expandShown);
150   if (toShow) {
151     qreal x;
152     if (inPortItem) {
153       x = Resource::Corner_Margin;
154       inPortItem->show();
155     } else {
156       x = Resource::Corner_Margin + Resource::DataPort_Width + Resource::Space_Margin;
157       outPortItem->show();
158     };
159     qreal y = Resource::Header_Height + nbPorts * (Resource::DataPort_Height + Resource::Space_Margin);
160
161     if (_maxPorts <= nbPorts) {
162       _maxPorts = nbPorts+1;
163       _height  = Resource::Header_Height + Resource::Border_Margin;
164       _height += _maxPorts * (Resource::DataPort_Height + Resource::Space_Margin);
165       _incHeight = _height; // must just be more than the actual increment of height
166       DEBTRACE("SceneElementaryNodeItem::autoPosNewPort _height=" << _height);
167     };
168
169     item->setTopLeft(QPointF(x, y));
170
171   } else {
172     _height = Resource::Header_Height + Resource::Border_Margin;
173     qreal y = Resource::Corner_Margin;
174     if (inPortItem) {
175       item->setTopLeft(QPointF(Resource::Corner_Margin, y));
176       inPortItem->hide();
177     } else {
178       item->setTopLeft(QPointF(Resource::Corner_Margin + Resource::DataPort_Width + Resource::Space_Margin, y));
179       outPortItem->hide();
180     };
181   };
182 }
183
184 void SceneElementaryNodeItem::popupMenu(QWidget *caller, const QPoint &globalPos)
185 {
186   ElementaryNodeMenu m;
187   m.popupMenu(caller, globalPos);
188 }
189
190 void SceneElementaryNodeItem::reorganizeShrinkExpand(ShrinkMode theShrinkMode)
191 {
192   DEBTRACE("SceneElementaryNodeItem::reorganizeShrinkExpand " << isExpanded() << " "  << _label.toStdString());
193   if (theShrinkMode != CurrentNode)
194     return;
195   shrinkExpandRecursive(!isExpanded(), true, theShrinkMode);
196   if (Scene::_autoComputeLinks)
197     {
198       SubjectProc* subproc = QtGuiContext::getQtCurrent()->getSubjectProc();
199       SceneItem *item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[subproc];
200       SceneComposedNodeItem *proc = dynamic_cast<SceneComposedNodeItem*>(item);
201       proc->rebuildLinks();
202     }
203 }
204
205 void SceneElementaryNodeItem::shrinkExpandRecursive(bool toExpand, bool fromHere, ShrinkMode theShrinkMode)
206 {
207   DEBTRACE("SceneElementaryNodeItem::shrinkExpandRecursive " << toExpand << " " << fromHere << " "  << isExpanded() << " " << _label.toStdString());
208   
209   bool toChangeShrinkState = false;
210   switch (theShrinkMode) {
211   case CurrentNode:
212     if (fromHere)
213       toChangeShrinkState = true;
214     break;
215   case ChildrenNodes:
216     if (fromHere)
217       toChangeShrinkState = true;
218     break;
219   case ElementaryNodes:
220     toChangeShrinkState = true;
221     break;
222   }
223   if (toChangeShrinkState && toExpand != isExpanded())
224     setExpanded(toExpand);
225
226   if (toExpand) {
227     if (toChangeShrinkState) {
228       _ancestorShrinked = false;
229       _shownState = expandShown;
230     } else {
231       if (isExpanded())
232         _shownState = expandShown;
233       else
234         _shownState = shrinkShown;
235     }
236   } else {
237     if (fromHere || theShrinkMode==ElementaryNodes) {
238       _shownState = shrinkShown;
239     } else {
240       _ancestorShrinked = true;
241       _shownState = shrinkHidden;
242     }
243   }
244
245   if (_shownState == shrinkHidden) // shrink of ancestor
246     setPos(0, 0);
247   else
248     setPos(_expandedPos);
249
250   reorganize();
251 }
252
253 void SceneElementaryNodeItem::reorganize()
254 {
255   DEBTRACE("SceneElementaryNodeItem::reorganize() " << _label.toStdString());
256
257   SubjectNode* snode = dynamic_cast<SubjectNode*>(_subject);
258   ElementaryNode* father = dynamic_cast<ElementaryNode*>(snode->getNode());
259   YASSERT(father);
260
261   _maxPorts = 0;
262
263   list<InPort*> plisti = father->getSetOfInPort();
264   list<InPort*>::iterator iti = plisti.begin();
265   int nbPorts = 0;
266   for (; iti != plisti.end(); ++iti)
267     {
268       Subject *sub = QtGuiContext::getQtCurrent()->_mapOfSubjectDataPort[(*iti)];
269       SceneItem *item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[sub];
270       autoPosNewPort(item, nbPorts);
271       nbPorts++;
272     }
273
274   list<OutPort*> plisto = father->getSetOfOutPort();
275   list<OutPort*>::iterator ito = plisto.begin();
276   nbPorts = 0;
277   for (; ito != plisto.end(); ++ito)
278     {
279       Subject *sub = QtGuiContext::getQtCurrent()->_mapOfSubjectDataPort[(*ito)];
280       SceneItem *item = QtGuiContext::getQtCurrent()->_mapOfSceneItem[sub];
281       autoPosNewPort(item, nbPorts);
282       nbPorts++;
283     }
284   updateLinks();
285 }
286
287 void SceneElementaryNodeItem::setShownState(shownState ss)
288 {
289   _shownState = ss;
290   if (_shownState == shrinkHidden)
291     {
292       _ancestorShrinked = true;
293       hide();
294     }
295   else
296     {
297       _ancestorShrinked = false;
298       show();
299     }
300   reorganize();
301 }
302