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/nodes/SoBaseColor.h>
16 #include <Inventor/nodes/SoScale.h>
17 #include <Inventor/nodes/SoSeparator.h>
18 #include <Inventor/nodes/SoTranslation.h>
19 #include <Inventor/nodes/SoTransform.h>
22 #include "colorlist.h"
23 #include "yscalemod.h"
25 #include "colorscalemod.h"
27 #include "defaultobj.h"
36 BarObj::BarObj(ViewObj::Shape shape
,
37 BarMod::Direction dir
,
38 BarMod::Modulation mod
,
39 BarMod::Grouping group
,
41 const DefaultObj
&defaults
,
44 BaseObj::Alignment align
)
45 : ModObj(baseFlag
, defaults
, x
, y
, cols
, rows
, align
),
52 _xSpace(defaults
.barSpaceX()),
53 _zSpace(defaults
.barSpaceZ()),
54 _labelSpace(defaults
.barSpaceLabel()),
57 _metLabels(new QStringList
),
59 _instLabels(new QStringList
)
64 for (i
= 0; i
< numSides
; i
++)
66 _labelColor
[0] = defaults
.labelColor(0);
67 _labelColor
[1] = defaults
.labelColor(1);
68 _labelColor
[2] = defaults
.labelColor(2);
74 const ColorSpec
*colSpec
= NULL
;
75 SoNode
*object
= ViewObj::object(_shape
);
76 SoSeparator
*labelSep
= NULL
;
77 SoSeparator
*metricSep
= NULL
;
78 SoSeparator
*instSep
= NULL
;
79 SoSeparator
*barSep
= new SoSeparator
;
80 SoSeparator
*baseSep
= new SoSeparator
;
81 SoTranslation
*objTran
= new SoTranslation
;
82 SoTranslation
*barTran
= new SoTranslation
;
83 SoTranslation
*baseTran
= new SoTranslation
;
84 SoTranslation
*modTran
= new SoTranslation
;
85 ColorScale
*colScale
= NULL
;
86 LabelSide metSide
= left
;
87 LabelSide instSide
= left
;
88 Text
**metText
= NULL
;
89 Text
**instText
= NULL
;
93 int numInstLabels
= 0;
96 if (pmDebug
& DBG_TRACE_APPL0
)
97 cerr
<< "BarObj::finishedAdd:" << endl
;
100 if (_metrics
.numMetrics() == 0) {
101 BaseObj::addBase(_root
);
102 pmprintf("%s: Error: Bar object has no metrics\n",
105 _width
= baseWidth();
106 _depth
= baseDepth();
110 _root
->addChild(objTran
);
112 if (_metLabels
->size() || _instLabels
->size()) {
113 labelSep
= new SoSeparator
;
114 _root
->addChild(labelSep
);
115 SoBaseColor
*base
= new SoBaseColor
;
116 base
->rgb
.setValue(_labelColor
[0], _labelColor
[1], _labelColor
[2]);
117 labelSep
->addChild(base
);
119 _root
->addChild(barSep
);
120 barSep
->addChild(barTran
);
121 barSep
->addChild(baseSep
);
122 baseSep
->addChild(baseTran
);
123 barSep
->addChild(modTran
);
124 BaseObj::addBase(baseSep
);
126 // Determine color mapping
129 colSpec
= theColorLists
.list((const char *)_colors
.toLatin1());
131 if (colSpec
!= NULL
) {
132 if (colSpec
->_scale
) {
133 if (_mod
== BarMod::yScale
) {
134 pmprintf("%s: Warning: Color scale ignored for Y-Scale Bar object.\n",
138 if (colSpec
->_list
.size() == 0)
139 colScale
= new ColorScale(0.0, 0.0, 1.0);
141 colScale
= new ColorScale(*(colSpec
->_list
[0]));
142 for (i
= 1; i
< colSpec
->_list
.size(); i
++)
143 colScale
->add(new ColorStep(*(colSpec
->_list
[i
]),
148 else if (_mod
== BarMod::color
|| _mod
== BarMod::colYScale
) {
149 pmprintf("%s: Warning: Expected color scale for color modulated Bar object.\n",
152 if (colSpec
->_list
.size() == 0)
153 colScale
= new ColorScale(0.0, 0.0, 1.0);
155 colScale
= new ColorScale(*(colSpec
->_list
[0]));
159 pmprintf("%s: Warning: No colours specified for Bar objects, defaulting to blue.\n",
162 if (_mod
== BarMod::color
|| _mod
== BarMod::colYScale
)
163 colScale
= new ColorScale(0.0, 0.0, 1.0);
166 if (_mod
== BarMod::yScale
) {
168 for (i
= 0; i
< colSpec
->_list
.size(); i
++)
169 _metrics
.add(*(colSpec
->_list
)[i
]);
170 _metrics
.resolveColors(MetricList::perMetric
);
173 // Generate Bar Modulate Object
174 if (_mod
== BarMod::yScale
)
175 _bars
= new BarMod(&_metrics
, object
, _dir
, _group
,
176 (float)_length
, (float)_maxHeight
, (float)_length
,
177 (float)_xSpace
, (float)_zSpace
);
179 _bars
= new BarMod(&_metrics
, *colScale
, object
, _dir
, _mod
, _group
,
180 (float)_length
, (float)_maxHeight
, (float)_length
,
181 (float)_xSpace
, (float)_zSpace
);
184 barSep
->addChild(_bars
->root());
189 if (_metLabels
->size()) {
190 if (_dir
== BarMod::instPerRow
)
201 metricSep
= new SoSeparator
;
202 labelSep
->addChild(metricSep
);
204 if (_metLabels
->size() < _metrics
.numMetrics())
205 numMetLabels
= _metLabels
->size();
207 numMetLabels
= _metrics
.numMetrics();
209 metText
= calcLabels(*_metLabels
, metSide
, numMetLabels
);
212 if (_instLabels
->size()) {
213 if (_dir
== BarMod::instPerCol
) {
215 if (_instDir
== away
)
222 if (_instDir
== away
)
228 instSep
= new SoSeparator
;
229 labelSep
->addChild(instSep
);
231 if (_instLabels
->size() < max
)
232 numInstLabels
= _instLabels
->size();
236 instText
= calcLabels(*_instLabels
, instSide
, numInstLabels
);
239 // Width and depth of bars only, effects of labels added later
241 _width
= _bars
->width();
242 _depth
= _bars
->depth();
247 metricSep
->addChild(doLabels(metText
, metSide
, numMetLabels
));
250 instSep
->addChild(doLabels(instText
, instSide
, numInstLabels
));
252 // Work out where the bars live
254 _bars
->regenerate(_length
, _length
, _xSpace
, _zSpace
);
255 _width
= _bars
->width();
256 _depth
= _bars
->depth();
258 baseTran
->translation
.setValue(_width
/ 2.0, 0.0, _depth
/ 2.0);
260 _width
+= (u_int32_t
)(baseWidth() + _margins
[left
] + _margins
[right
]+0.5);
261 _depth
+= (u_int32_t
)(baseDepth() + _margins
[above
] + _margins
[below
]+0.5);
263 objTran
->translation
.setValue((_width
/ -2.0), 0.0, (_depth
/ -2.0));
265 barTran
->translation
.setValue(_margins
[left
] + borderX(), 0.0,
266 _margins
[above
] + borderZ());
269 modTran
->translation
.setValue(0.0,
270 (BaseObj::state() ? baseHeight() : 0.0),
274 if (pmDebug
& DBG_TRACE_APPL0
)
275 cerr
<< "BarObj::finishedAdd: metric list = " << endl
279 if (_metrics
.numMetrics())
280 ViewObj::theNumModObjects
++;
291 BarObj::setTran(float xTran
, float zTran
, int setWidth
, int setDepth
)
293 BaseObj::setBaseSize(width() - _margins
[left
] - _margins
[right
],
294 depth() - _margins
[above
] - _margins
[below
]);
295 BaseObj::setTran(xTran
+ (width() / 2.0),
296 zTran
+ (depth() / 2.0),
301 operator<<(QTextStream
& os
, BarObj
const& rhs
)
308 BarObj::display(QTextStream
& os
) const
310 BaseObj::display(os
);
313 os
<< "No valid metrics" << endl
;
318 << (_dir
== BarMod::instPerCol
? "instPerCol" : "instPerRow")
319 << ", length = " << _length
<< ", xSpace = " << _xSpace
<< ", zSpace = "
320 << _zSpace
<< ", labelSpace = " << _labelSpace
<< ", rows = " << _rows
321 << ", cols = " << _cols
<< ", num bars = " << _bars
->numBars()
323 ViewObj::dumpShape(os
, _shape
);
324 os
<< ", margins: left = " << _margins
[left
] << ", right = "
325 << _margins
[right
] << ", above = " << _margins
[above
]
326 << ", below = " << _margins
[below
];
332 static QString myName
;
334 if (myName
.size() == 0) {
336 myName
= "Invalid bar object";
338 myName
= _bars
->modStr();
339 myName
.append(" Bar Object (");
340 myName
.append(_bars
->dirStr());
341 myName
.append(QChar(')'));
345 return (const char *)myName
.toLatin1();
349 BarObj::calcLabels(const QStringList
&labels
, LabelSide side
, int numLabels
)
356 text
= new Text
*[numLabels
];
359 if (pmDebug
& DBG_TRACE_APPL0
) {
360 cerr
<< "BarObj::calcLabels: " << numLabels
<< " labels on the ";
375 cerr
<< " side" << endl
;
379 // Create the text objects so that we know how big they are
381 for (i
= 0; i
< numLabels
; i
++) {
382 if (side
== above
|| side
== below
)
383 text
[i
] = new Text(labels
[i
], Text::down
, Text::medium
);
385 text
[i
] = new Text(labels
[i
], Text::right
, Text::medium
);
387 if (text
[i
]->width() > maxWidth
)
388 maxWidth
= text
[i
]->width();
389 if (text
[i
]->depth() > maxDepth
)
390 maxDepth
= text
[i
]->depth();
394 if (pmDebug
& DBG_TRACE_APPL0
)
395 cerr
<< "BarObj::calcLabels: maxWidth = " << maxWidth
396 << ", maxDepth = " << maxDepth
<< endl
;
399 // Determine if the size of the bars will need to be increased
401 if (side
== above
|| side
== below
) {
402 _margins
[side
] = maxDepth
+ _labelSpace
;
403 if (maxWidth
> _length
) {
407 if (pmDebug
& DBG_TRACE_APPL0
)
408 cerr
<< "BarObj::calcLabels: length (width) increased to "
415 _margins
[side
] = maxWidth
+ _labelSpace
;
416 if (maxDepth
> _length
) {
421 if (pmDebug
& DBG_TRACE_APPL0
)
422 cerr
<< "BarObj::calcLabels: length (depth) increased to "
431 BarObj::doLabels(Text
**text
, LabelSide side
, int numLabels
)
433 SoSeparator
*sep
= new SoSeparator
;
434 SoTranslation
*tran
= new SoTranslation
;
440 if (pmDebug
& DBG_TRACE_APPL0
) {
441 cerr
<< "BarObj::doLabels: " << numLabels
<< " labels on the ";
456 cerr
<< " side" << endl
;
462 // Determine the translation to the first label, subsequent labels
463 // are translated from the first
465 maxWidth
= _length
+ _xSpace
;
466 maxDepth
= _length
+ _zSpace
;
470 tran
->translation
.setValue(_margins
[left
] - _labelSpace
, 0.0,
471 _margins
[above
] + borderZ());
474 tran
->translation
.setValue(
475 _margins
[left
] + _width
+ baseWidth() + _labelSpace
,
476 0.0, _margins
[above
] + borderZ());
479 tran
->translation
.setValue(_margins
[left
] + borderX(), 0.0,
480 _margins
[above
] - _labelSpace
);
483 tran
->translation
.setValue(_margins
[left
] + borderX(), 0.0,
484 _margins
[above
] + _depth
+ baseDepth() + _labelSpace
);
491 if (pmDebug
& DBG_TRACE_APPL0
) {
493 tran
->translation
.getValue().getValue(x
, y
, z
);
494 cerr
<< "BarObj::doLabels: translation set to " << x
<< ',' << y
499 // Add each label to the scene graph
501 for (i
= 0; i
< numLabels
; i
++) {
502 SoSeparator
*labelSep
= new SoSeparator
;
503 sep
->addChild(labelSep
);
505 SoTranslation
*labelTran
= new SoTranslation
;
506 labelSep
->addChild(labelTran
);
510 labelTran
->translation
.setValue(0.0,
512 (maxDepth
* i
) + ((_length
- (float)text
[i
]->depth())/ 2.0));
515 labelTran
->translation
.setValue(text
[i
]->width(), 0.0,
516 (maxDepth
* i
) + ((_length
- (float)text
[i
]->depth())/ 2.0));
519 labelTran
->translation
.setValue(
520 (maxWidth
* i
) + ((_length
- (float)text
[i
]->width())/ 2.0),
524 labelTran
->translation
.setValue(
525 (maxWidth
* i
) + ((_length
- (float)text
[i
]->width())/ 2.0),
526 0.0, text
[i
]->depth());
532 labelSep
->addChild(text
[i
]->root());
535 // Do not delete contents, just the array pointer