Salome HOME
Merge from V6_main 01/04/2013
[modules/yacs.git] / src / genericgui / SceneHeaderNodeItem.cxx
1 // Copyright (C) 2006-2013  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.
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 "SceneHeaderNodeItem.hxx"
21 #include "SceneComposedNodeItem.hxx"
22 #include "SceneProcItem.hxx"
23 #include "SceneCtrlInPortItem.hxx"
24 #include "SceneCtrlOutPortItem.hxx"
25 #include "SceneInPortItem.hxx"
26 #include "SceneOutPortItem.hxx"
27 #include "Scene.hxx"
28
29 #include "QtGuiContext.hxx"
30 #include "GuiEditor.hxx"
31 #include "Resource.hxx"
32 #include "Menus.hxx"
33 #include <QGraphicsSceneHoverEvent>
34 #include <QGraphicsSceneMouseEvent>
35 #include <QPointF>
36
37 #include <cassert>
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 SceneHeaderNodeItem::SceneHeaderNodeItem(QGraphicsScene *scene, SceneItem *parent,
47                                          QString label)
48   : SceneHeaderItem(scene, parent, label)
49 {
50   _width  = 2*Resource::Corner_Margin + 2*Resource::DataPort_Width + Resource::Space_Margin;
51   _height = Resource::Header_Height;
52   _maxPorts = 0;
53
54   _header = 0;
55   _controlIn = 0;
56   _controlOut = 0;
57   _label = "H_" + _label;
58   _hasHeader = true;
59
60   _controlIn = new SceneCtrlInPortItem(_scene, this, "in");
61   _controlIn->setTopLeft(QPointF(Resource::Corner_Margin, Resource::Corner_Margin));
62
63   _header = new SceneHeaderItem(_scene, this, "header_"+_label);
64   _header->setText(label);
65   _header->setTopLeft(QPointF(Resource::Corner_Margin + Resource::CtrlPort_Width + Resource::Space_Margin, Resource::Corner_Margin));
66
67   _controlOut = new SceneCtrlOutPortItem(_scene, this, "out");
68   _controlOut->setTopLeft(QPointF(Resource::Corner_Margin + 2*Resource::DataPort_Width + Resource::Space_Margin - Resource::CtrlPort_Width, Resource::Corner_Margin));
69
70   if (QtGuiContext::getQtCurrent()->isEdition())
71     _brushColor = Resource::normalNodeBrushColor;
72   else
73     _brushColor = Resource::runNodeBrushColor;
74   _execState = YACS::UNDEFINED;
75   _sc = Resource::validNodeColor;
76   _stateDef = "";
77   _isProc = dynamic_cast<SceneProcItem*>(_parent);
78   _isValid = true;
79   _isEdited = false;
80 }
81
82 SceneHeaderNodeItem::~SceneHeaderNodeItem()
83 {
84 }
85
86 void SceneHeaderNodeItem::paint(QPainter *painter,
87                                 const QStyleOptionGraphicsItem *option,
88                                 QWidget *widget)
89 {
90   //DEBTRACE("SceneHeaderNodeItem::paint");
91   painter->save();
92
93   int x = Resource::Border_Margin + 1;
94   int y = Resource::Header_Height - Resource::Line_Space;
95   int w = Resource::Corner_Margin + 2*Resource::DataPort_Width + 2*Resource::Space_Margin;
96   if (_parent->getWidth() > w) w = _parent->getWidth() - Resource::Border_Margin;
97   QPen pen(getPenColor());
98   pen.setWidth(Resource::Line_Width);
99   painter->setPen(pen);
100   painter->drawLine(x, y, w, y);
101
102   x = Resource::Corner_Margin + Resource::CtrlPort_Width + Resource::Space_Margin;
103   y = Resource::Corner_Margin;
104   w = w - 2*Resource::CtrlPort_Width - 3*Resource::Space_Margin - Resource::Corner_Margin;
105   int h = Resource::CtrlPort_Height;
106   pen.setWidth(Resource::Thickness);
107   painter->setPen(pen);
108   
109   SceneNodeItem* father = dynamic_cast<SceneNodeItem*>(_parent);
110   bool expanded = (father && father->isExpanded());
111   QColor baseColor = getBrushColor();
112   if (expanded)
113     painter->setBrush(baseColor);
114   else
115     {
116        int h, s, v, a, h2;
117        baseColor.getHsv(&h, &s, &v, &a);
118        DEBTRACE("h="<<h<<" s="<<s<<" v="<<v);
119        h2 = h+60;
120        if (h>359) h2 = h2-359;
121        QLinearGradient gradient;
122        gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
123        gradient.setColorAt(0, baseColor.darker(200));
124        //gradient.setColorAt(1, baseColor.lighter(150));
125        //gradient.setColorAt(0, QColor::fromHsv(h-60, s, v, a));
126        gradient.setColorAt(1, QColor::fromHsv(h2, s, v, a));
127        QBrush brush(gradient);
128        painter->setBrush(brush);
129     }
130   painter->drawRoundedRect(QRect(x, y, w, h), Resource::Radius, Resource::Radius);
131
132   painter->restore();
133 }
134
135 void SceneHeaderNodeItem::setText(QString label)
136 {
137   if (_header) _header->setText(label);
138 }
139
140 qreal SceneHeaderNodeItem::getHeaderBottom() const
141 {
142   if (_hasHeader) {
143     return Resource::Header_Height + _maxPorts * (Resource::DataPort_Height + Resource::Space_Margin);
144   } else {
145     return 0;
146   };
147 }
148
149 void SceneHeaderNodeItem::autoPosControl(AbstractSceneItem *item)
150 {
151 }
152
153 void SceneHeaderNodeItem::autoPosNewPort(AbstractSceneItem *item)
154 {
155   DEBTRACE("SceneHeaderNodeItem::autoPosNewPort");
156   SceneInPortItem* inPortItem = dynamic_cast<SceneInPortItem*>(item);
157
158   int nbPorts;
159   qreal xLeft;
160   if (inPortItem) {
161     xLeft = Resource::Corner_Margin;
162     nbPorts = _inPorts.size();
163     _inPorts.push_back(inPortItem);
164   } else {
165     if (_parent->getWidth() > (2*Resource::Corner_Margin + 2*Resource::DataPort_Width + Resource::Space_Margin)) {
166       xLeft = _parent->getWidth() - Resource::Corner_Margin - Resource::DataPort_Width;
167     } else {
168       xLeft = Resource::Corner_Margin + Resource::DataPort_Width + Resource::Space_Margin;
169     };
170     nbPorts = _outPorts.size();
171     _outPorts.push_back(dynamic_cast<SceneOutPortItem*>(item));
172   };
173   qreal yTop   = Resource::Header_Height;
174   qreal deltaY = Resource::DataPort_Height + Resource::Space_Margin;
175   yTop += nbPorts * deltaY;
176   if (nbPorts >=_maxPorts) {
177     _maxPorts = nbPorts+1;
178   };
179   //DEBTRACE("left, top " << xLeft  << " " << yTop);
180   QPointF topLeft(xLeft, yTop);
181   item->setTopLeft(topLeft);
182   adaptComposedNode(dynamic_cast<SceneItem*>(item), deltaY);
183 }
184
185 void SceneHeaderNodeItem::reorganizePorts(shownState ss)
186 {
187   DEBTRACE("SceneHeaderNodeItem::reorganizePorts() " << ss << " " << _label.toStdString());
188
189   qreal yTop;
190   qreal href = Resource::Header_Height;
191   bool isShown = (ss != shrinkHidden);
192   if (!isShown) href = Resource::Corner_Margin;
193
194 std::list<SceneInPortItem*>::iterator iti = _inPorts.begin();
195   int nbPorts = 0;
196   for (; iti != _inPorts.end(); ++iti)
197     {
198       yTop = href + nbPorts * (Resource::DataPort_Height + Resource::Space_Margin);
199       QPointF topLeft(Resource::Corner_Margin, yTop);
200       (*iti)->setTopLeft(topLeft);
201       if (isShown) nbPorts++; // otherwise (shrink from ancestor) put all ports at the same position
202     }
203
204   std::list<SceneOutPortItem*>::iterator ito = _outPorts.begin();
205   nbPorts = 0;
206   qreal xLeft;
207   if (ss == expandShown) {
208     xLeft = _parent->getWidth() - Resource::Corner_Margin - Resource::DataPort_Width;
209   } else {
210     xLeft = Resource::Corner_Margin + Resource::DataPort_Width + Resource::Space_Margin;
211   };
212   for (; ito != _outPorts.end(); ++ito)
213     {
214       yTop = href + nbPorts * (Resource::DataPort_Height + Resource::Space_Margin);
215       QPointF topLeft(xLeft, yTop);
216       (*ito)->setTopLeft(topLeft);
217       if (isShown) nbPorts++; // otherwise (shrink from ancestor) put all ports at the same position
218     }
219   //updateLinks();
220 }
221
222 void SceneHeaderNodeItem::popupMenu(QWidget *caller, const QPoint &globalPos)
223 {
224   if (_parent) _parent->popupMenu(caller, globalPos);
225 //   HeaderNodeMenu m;
226 //   m.popupMenu(caller, globalPos);
227 }
228
229 void SceneHeaderNodeItem::adjustGeometry()
230 {
231   DEBTRACE("SceneHeaderNodeItem::adjustGeometry() " << _label.toStdString());
232   prepareGeometryChange();
233   _width = _parent->getWidth();
234   if (_header) _header->adjustGeometry();
235   adjustPosPorts();
236   update();
237 }
238
239 void SceneHeaderNodeItem::adjustPosPorts()
240 {
241   SceneNodeItem* father = dynamic_cast<SceneNodeItem*>(_parent);
242   YASSERT(father);
243   shownState ss = father->getShownState();
244   if (_controlOut)
245     {
246       int x = Resource::Corner_Margin + 2*Resource::DataPort_Width + Resource::Space_Margin;
247       if ((ss == expandShown)  && (_parent->getWidth() > (x + Resource::Corner_Margin)))
248         x = _parent->getWidth() - Resource::Corner_Margin;
249     _controlOut->setTopLeft(QPointF(x - Resource::CtrlPort_Width, Resource::Corner_Margin));
250   };
251   reorganizePorts(ss);
252 }
253
254 QRectF SceneHeaderNodeItem::getMinimalBoundingRect() const
255 {
256   qreal width  = 2*Resource::Corner_Margin + 2*Resource::DataPort_Width + Resource::Space_Margin;
257   qreal height = Resource::Header_Height + Resource::Border_Margin;
258   int nbPorts  = _inPorts.size();
259   if (_outPorts.size() > nbPorts) nbPorts = _outPorts.size();
260   if (nbPorts) height += nbPorts*(Resource::DataPort_Height + Resource::Space_Margin);
261   //DEBTRACE(nbPorts << " " << width << " " << height);
262   return QRectF(x(), y(), width, height);
263 }
264
265 void SceneHeaderNodeItem::adaptComposedNode(SceneItem* port, qreal deltaY)
266 {
267   DEBTRACE("SceneHeaderNodeItem::adaptComposedNode " << deltaY);
268   QPointF oldPos(x(),y() - deltaY);
269   if (_parent)
270     {
271       if (SceneComposedNodeItem *bloc = dynamic_cast<SceneComposedNodeItem*>(_parent))
272         bloc->collisionResolv(port, oldPos);
273       //_parent->checkGeometryChange();
274     }
275 }
276
277 void SceneHeaderNodeItem::setEdited(bool isEdited)
278 {
279   DEBTRACE("SceneHeaderNodeItem::setEdited " << isEdited);
280   if (isEdited)
281     _brushColor = Resource::editedNodeBrushColor;
282   else
283     {
284       if (QtGuiContext::getQtCurrent()->isEdition())
285         _brushColor = Resource::normalNodeBrushColor;
286       else
287         _brushColor = Resource::runNodeBrushColor;
288     }
289   if (isEdited != _isEdited)
290     _parent->update();
291   _isEdited = isEdited;
292 }
293
294 void SceneHeaderNodeItem::setValid(bool isValid)
295 {
296   DEBTRACE("SceneHeaderNodeItem::setValid " << isValid);
297   if (_isValid != isValid)
298     {
299       _isValid = isValid;
300       _parent->update();
301     }
302 }
303
304 void SceneHeaderNodeItem::setExecState(int execState)
305 {
306   DEBTRACE("SceneHeaderNodeItem::setExecState " << execState);
307   _execState = execState;
308   if (!_isValid) return;
309   QColor oldsc = _sc;
310   if (_isProc)
311     switch (_execState)
312       {
313       case YACS::NOTYETINITIALIZED: _sc = Resource::NOTYETINITIALIZED; _stateDef = "Not Yet Initialized"; break;
314       case YACS::INITIALISED:       _sc = Resource::INITIALISED      ; _stateDef = "Initialized"        ; break;
315       case YACS::RUNNING:           _sc = Resource::RUNNING          ; _stateDef = "Running"            ; break;
316       case YACS::WAITINGTASKS:      _sc = Resource::WAITINGTASKS     ; _stateDef = "Waiting Tasks"      ; break;
317       case YACS::PAUSED:            _sc = Resource::PAUSED           ; _stateDef = "Paused"             ; break;
318       case YACS::FINISHED:          _sc = Resource::FINISHED         ; _stateDef = "Finished"           ; break;
319       case YACS::STOPPED:           _sc = Resource::STOPPED          ; _stateDef = "Stopped"            ; break;
320       default:                      _sc = Resource::UNKNOWN          ; _stateDef = "Unknown Status"     ;
321       }
322   else
323     switch (_execState)
324       {
325       case YACS::UNDEFINED:         _sc = Resource::UNDEFINED        ; _stateDef = "UNDEFINED"          ; break;
326       case YACS::INVALID:           _sc = Resource::INVALID          ; _stateDef = "INVALID"            ; break;
327       case YACS::READY:             _sc = Resource::READY            ; _stateDef = "READY"              ; break;
328       case YACS::TOLOAD:            _sc = Resource::TOLOAD           ; _stateDef = "TOLOAD"             ; break;
329       case YACS::LOADED:            _sc = Resource::LOADED           ; _stateDef = "LOADED"             ; break;
330       case YACS::TOACTIVATE:        _sc = Resource::TOACTIVATE       ; _stateDef = "TOACTIVATE"         ; break;
331       case YACS::ACTIVATED:         _sc = Resource::ACTIVATED        ; _stateDef = "ACTIVATED"          ; break;
332       case YACS::DESACTIVATED:      _sc = Resource::DESACTIVATED     ; _stateDef = "DESACTIVATED"       ; break;
333       case YACS::DONE:              _sc = Resource::DONE             ; _stateDef = "DONE"               ; break;
334       case YACS::SUSPENDED:         _sc = Resource::SUSPENDED        ; _stateDef = "SUSPENDED"          ; break;
335       case YACS::LOADFAILED:        _sc = Resource::LOADFAILED       ; _stateDef = "LOADFAILED"         ; break;
336       case YACS::EXECFAILED:        _sc = Resource::EXECFAILED       ; _stateDef = "EXECFAILED"         ; break;
337       case YACS::PAUSE:             _sc = Resource::PAUSE            ; _stateDef = "PAUSE"              ; break;
338       case YACS::INTERNALERR:       _sc = Resource::INTERNALERR      ; _stateDef = "INTERNALERR"        ; break;
339       case YACS::DISABLED:          _sc = Resource::DISABLED         ; _stateDef = "DISABLED"           ; break;
340       case YACS::FAILED:            _sc = Resource::FAILED           ; _stateDef = "FAILED"             ; break;
341       case YACS::ERROR:             _sc = Resource::ERROR            ; _stateDef = "ERROR"              ; break;
342       default:                      _sc = Resource::DEFAULT          ; _stateDef = "---"                ;
343       }
344   DEBTRACE("  - stateDef = " << _stateDef.toStdString());
345   if(oldsc != _sc)
346     _parent->update();
347 }
348
349 SceneCtrlPortItem* SceneHeaderNodeItem::getCtrlInPortItem()
350 {
351   return _controlIn;
352 }
353
354 SceneCtrlPortItem* SceneHeaderNodeItem::getCtrlOutPortItem()
355 {
356   return _controlOut;
357 }
358
359
360
361 void SceneHeaderNodeItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
362 {
363   event->ignore();
364 }
365
366 void SceneHeaderNodeItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
367 {
368   event->ignore();
369 }
370
371 QColor SceneHeaderNodeItem::getValidColor()
372 {
373   if (_isValid)
374     return _sc;
375   else
376     return Resource::invalidNodeColor;
377 }