2 * Copyright (c) 1997 Silicon Graphics, Inc. All Rights Reserved.
3 * Copyright (c) 2009 Aconex. All Rights Reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 #include <Inventor/SoPath.h>
16 #include <Inventor/nodes/SoBaseColor.h>
17 #include <Inventor/nodes/SoTranslation.h>
18 #include <Inventor/nodes/SoScale.h>
19 #include <Inventor/nodes/SoSeparator.h>
20 #include <Inventor/nodes/SoSelection.h>
21 #include <Inventor/nodes/SoSwitch.h>
30 // Use debug flag LIBPMDA to trace stack refreshes
33 const float StackMod::theDefFillColor
[] = { 0.35, 0.35, 0.35 };
34 const char StackMod::theStackId
= 's';
40 StackMod::StackMod(MetricList
*metrics
, SoNode
*obj
, StackMod::Height height
)
51 int numValues
= _metrics
->numValues();
52 int numMetrics
= _metrics
->numMetrics();
54 float initScale
= 0.0;
57 _root
= new SoSeparator
;
61 if (_height
== fixed
) {
63 _text
.append(QChar('\n'));
69 initScale
= 1.0 / (float)numValues
;
72 if (pmDebug
& DBG_TRACE_APPL2
)
73 cerr
<< "StackMod::StackMod: numValues = "
74 << numValues
<< ", num of blocks = " << m
<< endl
78 for (m
= 0, v
= 0; m
< numMetrics
; m
++) {
79 const QmcMetric
&metric
= _metrics
->metric(m
);
80 for (i
= 0; i
< metric
.numValues(); i
++, v
++) {
83 block
._sep
= new SoSeparator
;
84 sprintf(buf
, "%c%d", theStackId
, v
);
85 block
._sep
->setName((SbName
)buf
);
86 _root
->addChild(block
._sep
);
88 block
._color
= new SoBaseColor
;
89 block
._color
->rgb
.setValue(_errorColor
.getValue());
90 block
._sep
->addChild(block
._color
);
92 block
._scale
= new SoScale
;
93 block
._scale
->scaleFactor
.setValue(1.0, initScale
, 1.0);
94 block
._sep
->addChild(block
._scale
);
96 block
._sep
->addChild(obj
);
98 block
._state
= Modulate::start
;
99 block
._selected
= false;
101 if (_height
== fixed
|| v
< numValues
- 1) {
102 block
._tran
= new SoTranslation();
103 block
._tran
->translation
.setValue(0.0, initScale
, 0.0);
104 _root
->addChild(block
._tran
);
113 if (_height
== fixed
) {
115 block
._sep
= new SoSeparator
;
116 _root
->addChild(block
._sep
);
117 sprintf(buf
, "%c%d", theStackId
, v
);
118 block
._sep
->setName((SbName
)buf
);
120 _switch
= new SoSwitch();
121 _switch
->whichChild
.setValue(SO_SWITCH_ALL
);
122 block
._sep
->addChild(_switch
);
124 block
._color
= new SoBaseColor
;
125 block
._color
->rgb
.setValue(theDefFillColor
);
126 _switch
->addChild(block
._color
);
129 block
._scale
= new SoScale
;
130 block
._scale
->scaleFactor
.setValue(1.0, 0.0, 1.0);
131 block
._state
= Modulate::start
;
132 block
._selected
= false;
133 _switch
->addChild(block
._scale
);
135 _switch
->addChild(obj
);
147 SoBaseColor
*tmpColor
= new SoBaseColor();
148 tmpColor
->rgb
.setValue(_errorColor
.getValue());
149 _root
->addChild(tmpColor
);
151 _root
->addChild(obj
);
156 StackMod::refresh(bool fetchFlag
)
158 int numValues
= _metrics
->numValues();
159 int numMetrics
= _metrics
->numMetrics();
163 static QVector
<double> values
;
166 if (pmDebug
& DBG_TRACE_LIBPMDA
)
167 cerr
<< endl
<< "StackMod::refresh" << endl
;
173 if (numValues
> values
.size())
174 values
.resize(numValues
);
176 for (m
= 0, v
= 0; m
< numMetrics
; m
++) {
177 QmcMetric
&metric
= _metrics
->metric(m
);
180 for (i
= 0; i
< metric
.numValues(); i
++, v
++) {
182 StackBlock
&block
= _blocks
[v
];
183 double &value
= values
[v
];
186 if (pmDebug
& DBG_TRACE_LIBPMDA
)
187 cerr
<< '[' << v
<< "] ";
190 if (metric
.error(i
) <= 0) {
191 if (block
._state
!= Modulate::error
) {
192 block
._color
->rgb
.setValue(_errorColor
.getValue());
193 block
._state
= Modulate::error
;
195 value
= Modulate::theMinScale
;
199 if (pmDebug
& DBG_TRACE_LIBPMDA
)
200 cerr
<< "Error, value set to " << value
<< endl
;
204 else if (block
._state
== Modulate::error
||
205 block
._state
== Modulate::start
) {
206 block
._state
= Modulate::normal
;
208 block
._color
->rgb
.setValue(_metrics
->color(v
).getValue());
210 block
._color
->rgb
.setValue(_metrics
->color(m
).getValue());
211 value
= metric
.value(i
) * theScale
;
212 if (value
< theMinScale
)
216 if (pmDebug
& DBG_TRACE_LIBPMDA
)
217 cerr
<< "Error->Normal, value = " << value
<< endl
;
222 value
= metric
.value(i
) * theScale
;
223 if (value
< theMinScale
)
227 if (pmDebug
& DBG_TRACE_LIBPMDA
)
228 cerr
<< "Normal, value = " << value
<< endl
;
236 if (pmDebug
& DBG_TRACE_LIBPMDA
)
237 cerr
<< "sum = " << sum
<< endl
;
240 if (sum
> theNormError
&& _height
!= util
) {
241 if (_blocks
[0]._state
!= Modulate::saturated
) {
242 for (v
= 0; v
< numValues
; v
++) {
243 StackBlock
&block
= _blocks
[v
];
244 if (block
._state
!= Modulate::error
) {
245 block
._color
->rgb
.setValue(Modulate::_saturatedColor
);
246 block
._state
= Modulate::saturated
;
252 for (m
= 0, v
= 0; m
< numMetrics
; m
++) {
253 QmcMetric
&metric
= _metrics
->metric(m
);
254 for (i
= 0; i
< metric
.numValues(); i
++, v
++) {
255 StackBlock
&block
= _blocks
[v
];
256 if (block
._state
== Modulate::saturated
) {
257 block
._state
= Modulate::normal
;
259 block
._color
->rgb
.setValue(_metrics
->color(v
).getValue());
261 block
._color
->rgb
.setValue(_metrics
->color(m
).getValue());
267 // Scale values to the range [0,1].
268 // Ensure that each block always has the minimum height to
269 // avoid planes clashing
271 if (sum
> 1.0 || _height
== util
) {
273 double max
= 1.0 - (theMinScale
* (numValues
- 1));
275 for (v
= 0; v
< numValues
; v
++) {
276 double &value
= values
[v
];
283 if (value
< theMinScale
)
289 for (v
= 0; v
< numValues
; v
++) {
291 StackBlock
&block
= _blocks
[v
];
292 double &value
= values
[v
];
295 if (pmDebug
& DBG_TRACE_LIBPMDA
)
296 cerr
<< '[' << v
<< "] scale = " << value
<< endl
;
299 block
._scale
->scaleFactor
.setValue(1.0, value
, 1.0);
301 if (v
< numValues
-1 || _height
== fixed
)
302 block
._tran
->translation
.setValue(0.0, value
, 0.0);
305 if (_height
== fixed
) {
307 if (sum
>= theMinScale
) {
308 _switch
->whichChild
.setValue(SO_SWITCH_ALL
);
309 _blocks
[v
]._scale
->scaleFactor
.setValue(1.0, sum
, 1.0);
312 _switch
->whichChild
.setValue(SO_SWITCH_NONE
);
313 _blocks
[v
]._scale
->scaleFactor
.setValue(1.0, theMinScale
, 1.0);
319 StackMod::dump(QTextStream
&os
) const
326 os
<< "Invalid metrics: " << pmErrStr(status()) << endl
;
329 for (m
= 0, v
= 0; m
< _metrics
->numMetrics(); m
++) {
330 QmcMetric
&metric
= _metrics
->metric(m
);
331 for (i
= 0; i
< metric
.numValues(); i
++, v
++) {
332 os
<< " [" << v
<< "]: ";
333 if (_blocks
[v
]._selected
== true)
337 dumpState(os
, _blocks
[v
]._state
);
339 metric
.dump(os
, true, i
);
346 StackMod::infoText(QString
&str
, bool selected
) const
353 if (selected
&& _selectCount
== 1) {
354 for (m
= 0, v
= 0; m
< _metrics
->numMetrics(); m
++) {
355 const QmcMetric
&metric
= _metrics
->metric(m
);
356 for (i
= 0; i
< metric
.numValues(); i
++, v
++)
357 if (_blocks
[v
]._selected
) {
366 if (v
>= _blocks
.size()) {
368 if (pmDebug
& DBG_TRACE_APPL2
)
369 cerr
<< "StackMod::infoText: infoText requested but nothing selected"
374 else if (_height
== fixed
&& v
== _blocks
.size() - 1) {
378 const QmcMetric
&metric
= _metrics
->metric(m
);
379 str
= metric
.spec(true, true, i
);
380 str
.append(QChar('\n'));
382 if (_blocks
[v
]._state
== Modulate::error
)
383 str
.append(theErrorText
);
384 else if (_blocks
[v
]._state
== Modulate::start
)
385 str
.append(theStartText
);
388 str
.append(value
.setNum(metric
.realValue(i
), 'g', 4));
389 str
.append(QChar(' '));
390 if (metric
.desc().units().length() > 0)
391 str
.append(metric
.desc().units());
393 str
.append(value
.setNum(metric
.value(i
) * 100.0, 'g', 4));
394 str
.append("% of expected max]");
400 StackMod::launch(Launch
&launch
, bool all
) const
403 bool launchAll
= all
;
408 // If the filler block is selected, launch all metrics
409 if (!launchAll
&& _height
== fixed
&&
410 _blocks
.last()._selected
== true) {
414 if (_height
== StackMod::util
)
415 launch
.startGroup("util");
417 launch
.startGroup("stack");
419 for (m
= 0, v
= 0; m
< _metrics
->numMetrics(); m
++) {
420 QmcMetric
&metric
= _metrics
->metric(m
);
421 for (i
= 0; i
< metric
.numValues(); i
++, v
++) {
422 if ((_selectCount
> 0 && _blocks
[v
]._selected
== true) ||
423 _selectCount
== 0 || launchAll
== true) {
425 launch
.addMetric(_metrics
->metric(m
),
436 StackMod::selectAll()
440 if (_selectCount
== _blocks
.size())
443 theModList
->selectAllId(_root
, _blocks
.size());
446 if (pmDebug
& DBG_TRACE_APPL2
)
447 cerr
<< "StackMod::selectAll" << endl
;
450 for (i
= 0; i
< _blocks
.size(); i
++) {
451 if (_blocks
[i
]._selected
== false) {
453 theModList
->selectSingle(_blocks
[i
]._sep
);
454 _blocks
[i
]._selected
= true;
460 StackMod::select(SoPath
*path
)
462 int metric
, inst
, value
;
464 findBlock(path
, metric
, inst
, value
, false);
465 if (value
< _blocks
.size() && _blocks
[value
]._selected
== false) {
466 _blocks
[value
]._selected
= true;
470 if (pmDebug
& DBG_TRACE_APPL2
)
471 cerr
<< "StackMod::select: value = " << value
472 << ", count = " << _selectCount
<< endl
;
479 StackMod::remove(SoPath
*path
)
481 int metric
, inst
, value
;
483 findBlock(path
, metric
, inst
, value
, false);
484 if (value
< _blocks
.size() && _blocks
[value
]._selected
== true) {
485 _blocks
[value
]._selected
= false;
489 if (pmDebug
& DBG_TRACE_APPL2
)
490 cerr
<< "StackMod::remove: value = " << value
491 << ", count = " << _selectCount
<< endl
;
497 else if (pmDebug
& DBG_TRACE_APPL2
)
498 cerr
<< "StackMod::remove: did not remove " << value
499 << ", count = " << _selectCount
<< endl
;
506 StackMod::selectInfo(SoPath
*path
)
508 findBlock(path
, _infoMetric
, _infoInst
, _infoValue
);
512 StackMod::removeInfo(SoPath
*)
514 _infoValue
= _blocks
.size();
515 _infoMetric
= _infoInst
= 0;
519 StackMod::findBlock(SoPath
*path
, int &metric
, int &inst
,
520 int &value
, bool idMetric
)
527 for (i
= path
->getLength() - 1; i
>= 0; --i
) {
528 node
= path
->getNode(i
);
529 str
= (char *)(node
->getName().getString());
530 if (strlen(str
) && str
[0] == theStackId
)
537 if (pmDebug
& DBG_TRACE_APPL2
)
538 cerr
<< "StackMod::findBlock: stack id = " << str
<< endl
;
541 sscanf(str
, "%c%d", &c
, &value
);
543 if (value
== 0 || idMetric
== false) {
550 while (m
< _metrics
->numMetrics()) {
551 i
= _metrics
->metric(m
).numValues();
565 value
= _blocks
.size();
570 if (pmDebug
& DBG_TRACE_APPL2
) {
571 cerr
<< "StackMod::findBlock: metric = " << metric
572 << ", inst = " << inst
<< ", value = " << value
<< endl
;
580 StackMod::setFillColor(const SbColor
&col
)
582 if (_sts
>= 0 && _height
== fixed
)
583 _blocks
.last()._color
->rgb
.setValue(col
.getValue());
587 StackMod::setFillColor(int packedcol
)
592 col
.setPackedValue(packedcol
, dummy
);