1 // Created on: 2004-06-22
3 // Copyright (c) 2004-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
17 #include <Aspect_ColorScale.hxx>
18 #include <Aspect_SequenceOfColor.hxx>
19 #include <Aspect_TypeOfColorScaleData.hxx>
20 #include <Aspect_TypeOfColorScalePosition.hxx>
21 #include <Precision.hxx>
22 #include <Quantity_Color.hxx>
23 #include <Standard_Type.hxx>
24 #include <TCollection_AsciiString.hxx>
25 #include <TCollection_ExtendedString.hxx>
26 #include <TColStd_SequenceOfExtendedString.hxx>
29 Aspect_ColorScale::Aspect_ColorScale()
36 myColorType( Aspect_TOCSD_AUTO ),
37 myLabelType( Aspect_TOCSD_AUTO ),
38 myAtBorder( Standard_True ),
39 myReversed( Standard_False ),
40 myLabelPos( Aspect_TOCSP_RIGHT ),
41 myTitlePos( Aspect_TOCSP_CENTER ),
50 Standard_Real Aspect_ColorScale::GetMin() const
55 Standard_Real Aspect_ColorScale::GetMax() const
60 void Aspect_ColorScale::GetRange (Standard_Real& theMin, Standard_Real& theMax) const
66 Aspect_TypeOfColorScaleData Aspect_ColorScale::GetLabelType() const
71 Aspect_TypeOfColorScaleData Aspect_ColorScale::GetColorType() const
76 Standard_Integer Aspect_ColorScale::GetNumberOfIntervals() const
81 TCollection_ExtendedString Aspect_ColorScale::GetTitle() const
86 TCollection_AsciiString Aspect_ColorScale::GetFormat() const
91 TCollection_ExtendedString Aspect_ColorScale::GetLabel (const Standard_Integer theIndex) const
93 if (GetLabelType() == Aspect_TOCSD_USER)
96 || theIndex >= myLabels.Length())
101 return myLabels.Value (theIndex + 1);
104 const Standard_Real aVal = GetNumber (theIndex);
105 const TCollection_AsciiString aFormat = Format();
106 Standard_Character aBuf[1024];
107 sprintf (aBuf, aFormat.ToCString(), aVal);
108 return TCollection_ExtendedString (aBuf);
111 Quantity_Color Aspect_ColorScale::GetColor (const Standard_Integer theIndex) const
113 if (GetColorType() == Aspect_TOCSD_USER)
116 || theIndex >= myColors.Length())
118 return Quantity_Color();
121 return myColors.Value (theIndex + 1);
123 return Quantity_Color (HueFromValue (theIndex, 0, GetNumberOfIntervals() - 1), 1.0, 1.0, Quantity_TOC_HLS);
126 void Aspect_ColorScale::GetLabels (TColStd_SequenceOfExtendedString& theLabels) const
129 for (Standard_Integer i = 1; i <= myLabels.Length(); i++)
130 theLabels.Append (myLabels.Value (i));
133 void Aspect_ColorScale::GetColors (Aspect_SequenceOfColor& theColors) const
136 for (Standard_Integer i = 1; i <= myColors.Length(); i++)
137 theColors.Append (myColors.Value (i));
140 Aspect_TypeOfColorScalePosition Aspect_ColorScale::GetLabelPosition() const
145 Aspect_TypeOfColorScalePosition Aspect_ColorScale::GetTitlePosition() const
150 Standard_Boolean Aspect_ColorScale::IsReversed() const
155 Standard_Boolean Aspect_ColorScale::IsLabelAtBorder() const
160 void Aspect_ColorScale::SetMin (const Standard_Real theMin)
162 SetRange (theMin, GetMax());
165 void Aspect_ColorScale::SetMax (const Standard_Real theMax)
167 SetRange (GetMin(), theMax);
170 void Aspect_ColorScale::SetRange (const Standard_Real theMin, const Standard_Real theMax)
172 if (myMin == theMin && myMax == theMax)
175 myMin = Min( theMin, theMax );
176 myMax = Max( theMin, theMax );
178 if (GetColorType() == Aspect_TOCSD_AUTO)
182 void Aspect_ColorScale::SetLabelType (const Aspect_TypeOfColorScaleData theType)
184 if (myLabelType == theType)
187 myLabelType = theType;
191 void Aspect_ColorScale::SetColorType (const Aspect_TypeOfColorScaleData theType)
193 if (myColorType == theType)
196 myColorType = theType;
200 void Aspect_ColorScale::SetNumberOfIntervals (const Standard_Integer theNum)
202 if (myInterval == theNum || theNum < 1)
209 void Aspect_ColorScale::SetTitle (const TCollection_ExtendedString& theTitle)
211 if (myTitle == theTitle)
218 void Aspect_ColorScale::SetFormat (const TCollection_AsciiString& theFormat)
220 if (myFormat == theFormat)
223 myFormat = theFormat;
224 if (GetLabelType() == Aspect_TOCSD_AUTO)
228 void Aspect_ColorScale::SetLabel (const TCollection_ExtendedString& theLabel, const Standard_Integer theIndex)
230 Standard_Boolean changed = Standard_False;
231 Standard_Integer i = theIndex < 0 ? myLabels.Length() + 1 : theIndex + 1;
232 if (i <= myLabels.Length()) {
233 changed = myLabels.Value (i) != theLabel;
234 myLabels.SetValue (i, theLabel);
237 changed = Standard_True;
238 while (i > myLabels.Length())
239 myLabels.Append (TCollection_ExtendedString());
240 myLabels.SetValue (i, theLabel);
246 void Aspect_ColorScale::SetColor (const Quantity_Color& theColor, const Standard_Integer theIndex)
248 Standard_Boolean changed = Standard_False;
249 Standard_Integer i = theIndex < 0 ? myColors.Length() + 1 : theIndex + 1;
250 if (i <= myColors.Length()) {
251 changed = myColors.Value (i) != theColor;
252 myColors.SetValue (i, theColor);
255 changed = Standard_True;
256 while ( i > myColors.Length() )
257 myColors.Append (Quantity_Color());
258 myColors.SetValue (i, theColor);
264 void Aspect_ColorScale::SetLabels (const TColStd_SequenceOfExtendedString& theSeq)
267 for (Standard_Integer i = 1; i <= theSeq.Length(); i++)
268 myLabels.Append (theSeq.Value (i));
271 void Aspect_ColorScale::SetColors (const Aspect_SequenceOfColor& theSeq)
274 for (Standard_Integer i = 1; i <= theSeq.Length(); i++)
275 myColors.Append (theSeq.Value (i));
278 void Aspect_ColorScale::SetLabelPosition (const Aspect_TypeOfColorScalePosition thePos)
280 if (myLabelPos == thePos)
287 void Aspect_ColorScale::SetTitlePosition (const Aspect_TypeOfColorScalePosition thePos)
289 if (myTitlePos == thePos)
296 void Aspect_ColorScale::SetReversed (const Standard_Boolean theReverse)
298 if (myReversed == theReverse)
301 myReversed = theReverse;
305 void Aspect_ColorScale::SetLabelAtBorder (const Standard_Boolean theOn)
307 if (myAtBorder == theOn)
314 void Aspect_ColorScale::GetPosition (Standard_Real& theX, Standard_Real& theY) const
320 Standard_Real Aspect_ColorScale::GetXPosition() const
325 Standard_Real Aspect_ColorScale::GetYPosition() const
330 void Aspect_ColorScale::SetPosition (const Standard_Real theX, const Standard_Real theY)
332 if (myXPos == theX && myYPos == theY)
341 void Aspect_ColorScale::SetXPosition (const Standard_Real theX)
343 SetPosition (theX, GetYPosition());
346 void Aspect_ColorScale::SetYPosition (const Standard_Real theY)
348 SetPosition (GetXPosition(), theY);
351 void Aspect_ColorScale::GetSize (Standard_Real& theWidth, Standard_Real& theHeight) const
354 theHeight = myHeight;
357 Standard_Real Aspect_ColorScale::GetWidth() const
362 Standard_Real Aspect_ColorScale::GetHeight() const
367 void Aspect_ColorScale::SetSize (const Standard_Real theWidth, const Standard_Real theHeight)
369 if (myWidth == theWidth && myHeight == theHeight)
373 myHeight = theHeight;
378 void Aspect_ColorScale::SetWidth (const Standard_Real theWidth)
380 SetSize (theWidth, GetHeight());
383 void Aspect_ColorScale::SetHeight (const Standard_Real theHeight)
385 SetSize (GetWidth(), theHeight);
388 void Aspect_ColorScale::SizeHint (Standard_Integer& theWidth, Standard_Integer& theHeight) const
390 Standard_Integer num = GetNumberOfIntervals();
392 Standard_Integer spacer = 5;
393 Standard_Integer textWidth = 0;
394 Standard_Integer textHeight = TextHeight ("");
395 Standard_Integer colorWidth = 20;
397 if (GetLabelPosition() != Aspect_TOCSP_NONE)
398 for (Standard_Integer idx = 0; idx < num; idx++)
399 textWidth = Max (textWidth, TextWidth (GetLabel (idx + 1)));
401 Standard_Integer scaleWidth = 0;
402 Standard_Integer scaleHeight = 0;
404 Standard_Integer titleWidth = 0;
405 Standard_Integer titleHeight = 0;
407 if (IsLabelAtBorder()) {
409 if (GetTitle().Length())
413 scaleWidth = colorWidth + textWidth + ( textWidth ? 3 : 2 ) * spacer;
414 scaleHeight = (Standard_Integer)( 1.5 * ( num + 1 ) * textHeight );
416 if (GetTitle().Length()) {
417 titleHeight = TextHeight (GetTitle()) + spacer;
418 titleWidth = TextWidth (GetTitle()) + 10;
421 theWidth = Max (titleWidth, scaleWidth);
422 theHeight = scaleHeight + titleHeight;
425 void Aspect_ColorScale::DrawScale ( const Quantity_Color& theBgColor,
426 const Standard_Integer theX, const Standard_Integer theY,
427 const Standard_Integer theWidth, const Standard_Integer theHeight)
432 Standard_Integer num = GetNumberOfIntervals();
433 Aspect_TypeOfColorScalePosition labPos = GetLabelPosition();
435 Standard_Integer spacer = 5;
436 Standard_Integer textWidth = 0;
437 Standard_Integer textHeight = TextHeight ("");
439 Standard_Boolean drawLabel = GetLabelPosition() != Aspect_TOCSP_NONE;
441 TCollection_ExtendedString aTitle = GetTitle();
443 Standard_Integer titleHeight = 0;
445 Standard_Integer aGray = (Standard_Integer)(255 * ( theBgColor.Red() * 11 + theBgColor.Green() * 16 + theBgColor.Blue() * 5 ) / 32);
446 Quantity_Color aFgColor (aGray < 128 ? Quantity_NOC_WHITE : Quantity_NOC_BLACK);
449 if (aTitle.Length()) {
450 titleHeight = TextHeight (aTitle) + 2 * spacer;
451 PaintText (aTitle, theX + spacer, theY + spacer, aFgColor);
454 Standard_Boolean reverse = IsReversed();
456 Aspect_SequenceOfColor colors;
457 TColStd_SequenceOfExtendedString labels;
458 for (int idx = 0; idx < num; idx++) {
460 colors.Append (GetColor (idx));
461 labels.Append (GetLabel (idx));
464 colors.Prepend (GetColor (idx));
465 labels.Prepend (GetLabel (idx));
469 if (IsLabelAtBorder()) {
471 labels.Append (GetLabel (num));
473 labels.Prepend (GetLabel (num));
477 for (Standard_Integer i = 1; i <= labels.Length(); i++)
478 textWidth = Max (textWidth, TextWidth (labels.Value (i)));
480 Standard_Integer lab = labels.Length();
482 Standard_Real spc = ( theHeight - ( ( Min (lab, 2) + Abs (lab - num - 1) ) * textHeight ) - titleHeight );
483 Standard_Real val = spc != 0 ? 1.0 * ( lab - Min (lab, 1) ) * textHeight / spc : 0;
485 Standard_Real fPart = modf (val, &iPart);
486 Standard_Integer filter = (Standard_Integer)iPart + ( fPart != 0 ? 1 : 0 );
488 Standard_Real step = 1.0 * ( theHeight - ( lab - num + Abs (lab - num - 1) ) * textHeight - titleHeight ) / num;
490 Standard_Integer ascent = 0;
491 Standard_Integer colorWidth = Max (5, Min (20, theWidth - textWidth - 3 * spacer));
492 if (labPos == Aspect_TOCSP_CENTER || !drawLabel)
493 colorWidth = theWidth - 2 * spacer;
496 Standard_Integer x = theX + spacer;
497 if (labPos == Aspect_TOCSP_LEFT)
498 x += textWidth + ( textWidth ? 1 : 0 ) * spacer;
500 Standard_Real offset = 1.0 * textHeight / 2 * ( lab - num + Abs (lab - num - 1) ) + titleHeight;
501 for (Standard_Integer ci = 1; ci <= colors.Length() && step > 0; ci++ ) {
502 Standard_Integer y = (Standard_Integer)( theY + ( ci - 1 )* step + offset);
503 Standard_Integer h = (Standard_Integer)( theY + ( ci ) * step + offset ) - y;
504 PaintRect (x, y, colorWidth, h, colors.Value (ci), Standard_True);
508 PaintRect (x - 1, (Standard_Integer)(theY + offset - 1), colorWidth + 2, (Standard_Integer)(colors.Length() * step + 2), aFgColor);
511 offset = 1.0 * Abs (lab - num - 1) * ( step - textHeight ) / 2 + 1.0 * Abs (lab - num - 1) * textHeight / 2;
512 offset += titleHeight;
513 if (drawLabel && labels.Length() && filter > 0) {
514 Standard_Integer i1 = 0;
515 Standard_Integer i2 = lab - 1;
516 Standard_Integer last1 (i1), last2 (i2);
519 case Aspect_TOCSP_NONE:
520 case Aspect_TOCSP_LEFT:
522 case Aspect_TOCSP_CENTER:
523 x += ( colorWidth - textWidth ) / 2;
525 case Aspect_TOCSP_RIGHT:
526 x += colorWidth + spacer;
529 while (i2 - i1 >= filter || ( i2 == 0 && i1 == 0 )) {
530 Standard_Integer pos1 = i1;
531 Standard_Integer pos2 = lab - 1 - i2;
532 if (filter && !( pos1 % filter )) {
533 PaintText (labels.Value (i1 + 1), x, (Standard_Integer)( theY + i1 * step + ascent + offset ), aFgColor);
536 if (filter && !( pos2 % filter )) {
537 PaintText (labels.Value (i2 + 1), x, (Standard_Integer)( theY + i2 * step + ascent + offset ), aFgColor);
543 Standard_Integer pos = i1;
544 Standard_Integer i0 = -1;
545 while (pos <= i2 && i0 == -1) {
546 if (filter && !( pos % filter ) && Abs (pos - last1) >= filter && Abs (pos - last2) >= filter)
552 PaintText (labels.Value (i0 + 1), x, (Standard_Integer)( theY + i0 * step + ascent + offset ), aFgColor);
558 Standard_Boolean Aspect_ColorScale::BeginPaint()
560 return Standard_True;
563 Standard_Boolean Aspect_ColorScale::EndPaint()
565 return Standard_True;
568 void Aspect_ColorScale::UpdateColorScale()
572 TCollection_AsciiString Aspect_ColorScale::Format() const
577 Standard_Real Aspect_ColorScale::GetNumber (const Standard_Integer theIndex) const
579 Standard_Real aNum = 0;
580 if (GetNumberOfIntervals() > 0)
581 aNum = GetMin() + theIndex * ( Abs (GetMax() - GetMin()) / GetNumberOfIntervals() );
585 Standard_Integer Aspect_ColorScale::HueFromValue (const Standard_Integer theValue,
586 const Standard_Integer theMin, const Standard_Integer theMax)
588 Standard_Integer minLimit (0), maxLimit (230);
590 Standard_Integer aHue = maxLimit;
591 if (theMin != theMax)
592 aHue = (Standard_Integer)( maxLimit - ( maxLimit - minLimit ) * ( theValue - theMin ) / ( theMax - theMin ) );
594 aHue = Min (Max (minLimit, aHue), maxLimit);
599 Standard_Integer Aspect_ColorScale::GetTextHeight() const {
603 void Aspect_ColorScale::SetTextHeight (const Standard_Integer theHeight) {
604 myTextHeight = theHeight;
609 Standard_Boolean Aspect_ColorScale::FindColor (const Standard_Real theValue,
610 Quantity_Color& theColor) const
612 return FindColor (theValue, myMin, myMax, myInterval, theColor);
616 Standard_Boolean Aspect_ColorScale::FindColor (const Standard_Real theValue,
617 const Standard_Real theMin,
618 const Standard_Real theMax,
619 const Standard_Integer theColorsCount,
620 Quantity_Color& theColor)
622 if(theValue<theMin || theValue>theMax || theMax<theMin)
623 return Standard_False;
627 Standard_Real IntervNumber = 0;
628 if(Abs (theMax-theMin) > Precision::Approximation())
629 IntervNumber = Floor (Standard_Real( theColorsCount ) * ( theValue - theMin ) / ( theMax - theMin ));
631 Standard_Integer Interv = Standard_Integer (IntervNumber);
633 theColor = Quantity_Color (HueFromValue (Interv, 0, theColorsCount - 1), 1.0, 1.0, Quantity_TOC_HLS);
635 return Standard_True;