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.
16 #include <Aspect_ColorScale.ixx>
18 #include <Aspect_ColorMap.hxx>
19 #include <Aspect_ColorMapEntry.hxx>
20 #include <Aspect_SequenceOfColor.hxx>
21 #include <Aspect_TypeOfColorScaleData.hxx>
22 #include <Aspect_TypeOfColorScalePosition.hxx>
24 #include <TCollection_AsciiString.hxx>
25 #include <TCollection_ExtendedString.hxx>
26 #include <TColStd_SequenceOfExtendedString.hxx>
28 #include <Precision.hxx>
32 Aspect_ColorScale::Aspect_ColorScale()
39 myColorType( Aspect_TOCSD_AUTO ),
40 myLabelType( Aspect_TOCSD_AUTO ),
41 myAtBorder( Standard_True ),
42 myReversed( Standard_False ),
43 myLabelPos( Aspect_TOCSP_RIGHT ),
44 myTitlePos( Aspect_TOCSP_CENTER ),
53 Standard_Real Aspect_ColorScale::GetMin() const
58 Standard_Real Aspect_ColorScale::GetMax() const
63 void Aspect_ColorScale::GetRange( Standard_Real& aMin, Standard_Real& aMax ) const
69 Aspect_TypeOfColorScaleData Aspect_ColorScale::GetLabelType() const
74 Aspect_TypeOfColorScaleData Aspect_ColorScale::GetColorType() const
79 Standard_Integer Aspect_ColorScale::GetNumberOfIntervals() const
84 TCollection_ExtendedString Aspect_ColorScale::GetTitle() const
89 TCollection_AsciiString Aspect_ColorScale::GetFormat() const
94 TCollection_ExtendedString Aspect_ColorScale::GetLabel( const Standard_Integer anIndex ) const
96 TCollection_ExtendedString aLabel;
97 if ( anIndex >= 0 && anIndex < myLabels.Length() )
98 aLabel = myLabels.Value( anIndex + 1 );
102 Quantity_Color Aspect_ColorScale::GetColor( const Standard_Integer anIndex ) const
104 Quantity_Color aColor;
105 if ( anIndex >= 0 && anIndex < myColors.Length() )
106 aColor = myColors.Value( anIndex + 1 );
110 void Aspect_ColorScale::GetLabels( TColStd_SequenceOfExtendedString& aLabels ) const
113 for ( Standard_Integer i = 1; i <= myLabels.Length(); i++ )
114 aLabels.Append( myLabels.Value( i ) );
117 void Aspect_ColorScale::GetColors( Aspect_SequenceOfColor& aColors ) const
120 for ( Standard_Integer i = 1; i <= myColors.Length(); i++ )
121 aColors.Append( myColors.Value( i ) );
124 Aspect_TypeOfColorScalePosition Aspect_ColorScale::GetLabelPosition() const
129 Aspect_TypeOfColorScalePosition Aspect_ColorScale::GetTitlePosition() const
134 Standard_Boolean Aspect_ColorScale::IsReversed() const
139 Standard_Boolean Aspect_ColorScale::IsLabelAtBorder() const
144 void Aspect_ColorScale::SetMin( const Standard_Real aMin )
146 SetRange( aMin, GetMax() );
149 void Aspect_ColorScale::SetMax( const Standard_Real aMax )
151 SetRange( GetMin(), aMax );
154 void Aspect_ColorScale::SetRange( const Standard_Real aMin, const Standard_Real aMax )
156 if ( myMin == aMin && myMax == aMax )
159 myMin = Min( aMin, aMax );
160 myMax = Max( aMin, aMax );
162 if ( GetColorType() == Aspect_TOCSD_AUTO )
166 void Aspect_ColorScale::SetLabelType( const Aspect_TypeOfColorScaleData aType )
168 if ( myLabelType == aType )
175 void Aspect_ColorScale::SetColorType( const Aspect_TypeOfColorScaleData aType )
177 if ( myColorType == aType )
184 void Aspect_ColorScale::SetNumberOfIntervals( const Standard_Integer aNum )
186 if ( myInterval == aNum || aNum < 1 )
193 void Aspect_ColorScale::SetTitle( const TCollection_ExtendedString& aTitle )
195 if ( myTitle == aTitle )
202 void Aspect_ColorScale::SetFormat( const TCollection_AsciiString& aFormat )
204 if ( myFormat == aFormat )
208 if ( GetLabelType() == Aspect_TOCSD_AUTO )
212 void Aspect_ColorScale::SetLabel( const TCollection_ExtendedString& aLabel, const Standard_Integer anIndex )
214 Standard_Boolean changed = Standard_False;
215 Standard_Integer i = anIndex < 1 ? myLabels.Length() + 1 : anIndex;
216 if ( i <= myLabels.Length() ) {
217 changed = myLabels.Value( i ) != aLabel;
218 myLabels.SetValue( i, aLabel );
221 changed = Standard_True;
222 while ( i > myLabels.Length() )
223 myLabels.Append( TCollection_ExtendedString() );
224 myLabels.SetValue( i, aLabel );
230 void Aspect_ColorScale::SetColor(const Quantity_Color& aColor, const Standard_Integer anIndex )
232 Standard_Boolean changed = Standard_False;
233 Standard_Integer i = anIndex < 1 ? myLabels.Length() + 1 : anIndex;
234 if ( i <= myColors.Length() ) {
235 changed = myColors.Value( i ) != aColor;
236 myColors.SetValue( i, aColor );
239 changed = Standard_True;
240 while ( i > myColors.Length() )
241 myColors.Append( Quantity_Color() );
242 myColors.SetValue( i, aColor );
248 void Aspect_ColorScale::SetLabels( const TColStd_SequenceOfExtendedString& aSeq )
251 for ( Standard_Integer i = 1; i <= aSeq.Length(); i++ )
252 myLabels.Append( aSeq.Value( i ) );
255 void Aspect_ColorScale::SetColors( const Handle(Aspect_ColorMap)& aMap )
258 if ( !aMap.IsNull() )
259 for ( Standard_Integer i = 1; i <= aMap->Size(); i++ )
260 myColors.Append( aMap->Entry( i ).Color() );
263 void Aspect_ColorScale::SetColors( const Aspect_SequenceOfColor& aSeq )
266 for ( Standard_Integer i = 1; i <= aSeq.Length(); i++ )
267 myColors.Append( aSeq.Value( i ) );
270 void Aspect_ColorScale::SetLabelPosition( const Aspect_TypeOfColorScalePosition aPos )
272 if ( myLabelPos == aPos )
279 void Aspect_ColorScale::SetTitlePosition( const Aspect_TypeOfColorScalePosition aPos )
281 if ( myTitlePos == aPos )
288 void Aspect_ColorScale::SetReversed( const Standard_Boolean aReverse )
290 if ( myReversed == aReverse )
293 myReversed = aReverse;
297 void Aspect_ColorScale::SetLabelAtBorder( const Standard_Boolean anOn )
299 if ( myAtBorder == anOn )
306 void Aspect_ColorScale::GetPosition( Standard_Real& aX, Standard_Real& aY ) const
312 Standard_Real Aspect_ColorScale::GetXPosition() const
317 Standard_Real Aspect_ColorScale::GetYPosition() const
322 void Aspect_ColorScale::SetPosition( const Standard_Real aX, const Standard_Real aY )
324 if ( myXPos == aX && myYPos == aY )
333 void Aspect_ColorScale::SetXPosition( const Standard_Real aX )
335 SetPosition( aX, GetYPosition() );
338 void Aspect_ColorScale::SetYPosition( const Standard_Real aY )
340 SetPosition( GetXPosition(), aY );
343 void Aspect_ColorScale::GetSize( Standard_Real& aWidth, Standard_Real& aHeight ) const
349 Standard_Real Aspect_ColorScale::GetWidth() const
354 Standard_Real Aspect_ColorScale::GetHeight() const
359 void Aspect_ColorScale::SetSize( const Standard_Real aWidth, const Standard_Real aHeight )
361 if ( myWidth == aWidth && myHeight == aHeight )
370 void Aspect_ColorScale::SetWidth( const Standard_Real aWidth )
372 SetSize( aWidth, GetHeight() );
375 void Aspect_ColorScale::SetHeight( const Standard_Real aHeight )
377 SetSize( GetWidth(), aHeight );
380 void Aspect_ColorScale::SizeHint( Standard_Integer& aWidth, Standard_Integer& aHeight ) const
382 Standard_Integer num = GetNumberOfIntervals();
384 Standard_Integer spacer = 5;
385 Standard_Integer textWidth = 0;
386 Standard_Integer textHeight = TextHeight( "" );
387 Standard_Integer colorWidth = 20;
389 if ( GetLabelPosition() != Aspect_TOCSP_NONE )
390 for ( Standard_Integer idx = 0; idx < num; idx++ )
391 textWidth = Max( textWidth, TextWidth( GetCurrentLabel( idx + 1 ) ) );
393 Standard_Integer scaleWidth = 0;
394 Standard_Integer scaleHeight = 0;
396 Standard_Integer titleWidth = 0;
397 Standard_Integer titleHeight = 0;
399 if ( IsLabelAtBorder() ) {
401 if ( GetTitle().Length() )
405 scaleWidth = colorWidth + textWidth + ( textWidth ? 3 : 2 ) * spacer;
406 scaleHeight = (Standard_Integer)( 1.5 * ( num + 1 ) * textHeight );
408 if ( GetTitle().Length() ) {
409 titleHeight = TextHeight( GetTitle() ) + spacer;
410 titleWidth = TextWidth( GetTitle() ) + 10;
413 aWidth = Max( titleWidth, scaleWidth );
414 aHeight = scaleHeight + titleHeight;
417 void Aspect_ColorScale::DrawScale( const Quantity_Color& aBgColor,
418 const Standard_Integer X, const Standard_Integer Y,
419 const Standard_Integer W, const Standard_Integer H )
424 Standard_Integer num = GetNumberOfIntervals();
425 Aspect_TypeOfColorScalePosition labPos = GetLabelPosition();
427 Standard_Integer spacer = 5;
428 Standard_Integer textWidth = 0;
429 Standard_Integer textHeight = TextHeight( "" );
431 Standard_Boolean drawLabel = GetLabelPosition() != Aspect_TOCSP_NONE;
433 TCollection_ExtendedString aTitle = GetTitle();
435 Standard_Integer titleHeight = 0;
437 Standard_Integer aGray = (Standard_Integer)(255 * ( aBgColor.Red() * 11 + aBgColor.Green() * 16 + aBgColor.Blue() * 5 ) / 32);
438 Quantity_Color aFgColor( aGray < 128 ? Quantity_NOC_WHITE : Quantity_NOC_BLACK );
441 if ( aTitle.Length() ) {
442 titleHeight = TextHeight( aTitle ) + 2 * spacer;
443 PaintText( aTitle, X + spacer, Y + spacer, aFgColor );
446 Standard_Boolean reverse = IsReversed();
448 Aspect_SequenceOfColor colors;
449 TColStd_SequenceOfExtendedString labels;
450 for ( int idx = 0; idx < num; idx++ ) {
452 colors.Append( GetCurrentColor( idx ) );
453 labels.Append( GetCurrentLabel( idx ) );
456 colors.Prepend( GetCurrentColor( idx ) );
457 labels.Prepend( GetCurrentLabel( idx ) );
461 if ( IsLabelAtBorder() ) {
463 labels.Append( GetCurrentLabel( num ) );
465 labels.Prepend( GetCurrentLabel( num ) );
469 for ( Standard_Integer i = 1; i <= labels.Length(); i++ )
470 textWidth = Max( textWidth, TextWidth( labels.Value( i ) ) );
472 Standard_Integer lab = labels.Length();
474 Standard_Real spc = ( H - ( ( Min( lab, 2 ) + Abs( lab - num - 1 ) ) * textHeight ) - titleHeight );
475 Standard_Real val = spc != 0 ? 1.0 * ( lab - Min( lab, 2 ) ) * textHeight / spc : 0;
477 Standard_Real fPart = modf( val, &iPart );
478 Standard_Integer filter = (Standard_Integer)iPart + ( fPart != 0 ? 1 : 0 );
480 Standard_Real step = 1.0 * ( H - ( lab - num + Abs( lab - num - 1 ) ) * textHeight - titleHeight ) / num;
482 Standard_Integer ascent = 0;
483 Standard_Integer colorWidth = Max( 5, Min( 20, W - textWidth - 3 * spacer ) );
484 if ( labPos == Aspect_TOCSP_CENTER || !drawLabel )
485 colorWidth = W - 2 * spacer;
488 Standard_Integer x = X + spacer;
489 if ( labPos == Aspect_TOCSP_LEFT )
490 x += textWidth + ( textWidth ? 1 : 0 ) * spacer;
492 Standard_Real offset = 1.0 * textHeight / 2 * ( lab - num + Abs( lab - num - 1 ) ) + titleHeight;
493 for ( Standard_Integer ci = 1; ci <= colors.Length() && step > 0; ci++ ) {
494 Standard_Integer y = (Standard_Integer)( Y + ( ci - 1 )* step + offset );
495 Standard_Integer h = (Standard_Integer)( Y + ( ci ) * step + offset ) - y;
496 PaintRect( x, y, colorWidth, h, colors.Value( ci ), Standard_True );
500 PaintRect( x - 1, (Standard_Integer)(Y + offset - 1), colorWidth + 2, (Standard_Integer)(colors.Length() * step + 2), aFgColor );
503 offset = 1.0 * Abs( lab - num - 1 ) * ( step - textHeight ) / 2 + 1.0 * Abs( lab - num - 1 ) * textHeight / 2;
504 offset += titleHeight;
505 if ( drawLabel && labels.Length() && filter > 0 ) {
506 Standard_Integer i1 = 0;
507 Standard_Integer i2 = lab - 1;
508 Standard_Integer last1( i1 ), last2( i2 );
511 case Aspect_TOCSP_NONE:
512 case Aspect_TOCSP_LEFT:
514 case Aspect_TOCSP_CENTER:
515 x += ( colorWidth - textWidth ) / 2;
517 case Aspect_TOCSP_RIGHT:
518 x += colorWidth + spacer;
521 while ( i2 - i1 >= filter || ( i2 == 0 && i1 == 0 ) ) {
522 Standard_Integer pos1 = i1;
523 Standard_Integer pos2 = lab - 1 - i2;
524 if ( filter && !( pos1 % filter ) ) {
525 PaintText( labels.Value( i1 + 1 ), x, (Standard_Integer)( Y + i1 * step + ascent + offset ), aFgColor );
528 if ( filter && !( pos2 % filter ) ) {
529 PaintText( labels.Value( i2 + 1 ), x, (Standard_Integer)( Y + i2 * step + ascent + offset ), aFgColor );
535 Standard_Integer pos = i1;
536 Standard_Integer i0 = -1;
537 while ( pos <= i2 && i0 == -1 ) {
538 if ( filter && !( pos % filter ) && Abs( pos - last1 ) >= filter && Abs( pos - last2 ) >= filter )
544 PaintText( labels.Value( i0 + 1 ), x, (Standard_Integer)( Y + i0 * step + ascent + offset ), aFgColor );
550 Standard_Boolean Aspect_ColorScale::BeginPaint()
552 return Standard_True;
555 Standard_Boolean Aspect_ColorScale::EndPaint()
557 return Standard_True;
560 void Aspect_ColorScale::UpdateColorScale()
564 TCollection_AsciiString Aspect_ColorScale::Format() const
569 TCollection_ExtendedString Aspect_ColorScale::GetCurrentLabel( const Standard_Integer anIndex ) const
571 TCollection_ExtendedString aLabel;
572 if ( GetLabelType() == Aspect_TOCSD_USER )
573 aLabel = GetLabel( anIndex );
575 Standard_Real val = GetNumber( anIndex );
576 Standard_Character buf[1024];
577 TCollection_AsciiString aFormat = Format();
578 sprintf( buf, aFormat.ToCString(), val );
579 aLabel = TCollection_ExtendedString( buf );
585 Quantity_Color Aspect_ColorScale::GetCurrentColor( const Standard_Integer anIndex ) const
587 Quantity_Color aColor;
588 if ( GetColorType() == Aspect_TOCSD_USER )
589 aColor = GetColor( anIndex );
591 aColor = Quantity_Color( HueFromValue( anIndex, 0, GetNumberOfIntervals() - 1 ), 1.0, 1.0, Quantity_TOC_HLS );
595 Standard_Real Aspect_ColorScale::GetNumber( const Standard_Integer anIndex ) const
597 Standard_Real aNum = 0;
598 if ( GetNumberOfIntervals() > 0 )
599 aNum = GetMin() + anIndex * ( Abs( GetMax() - GetMin() ) / GetNumberOfIntervals() );
603 Standard_Integer Aspect_ColorScale::HueFromValue( const Standard_Integer aValue,
604 const Standard_Integer aMin, const Standard_Integer aMax )
606 Standard_Integer minLimit( 0 ), maxLimit( 230 );
608 Standard_Integer aHue = maxLimit;
610 aHue = (Standard_Integer)( maxLimit - ( maxLimit - minLimit ) * ( aValue - aMin ) / ( aMax - aMin ) );
612 aHue = Min( Max( minLimit, aHue ), maxLimit );
617 Standard_Integer Aspect_ColorScale::GetTextHeight() const {
621 void Aspect_ColorScale::SetTextHeight(const Standard_Integer aHeigh) {
622 myTextHeight = aHeigh;
627 Standard_Boolean Aspect_ColorScale::FindColor( const Standard_Real aValue,
628 Quantity_Color& aColor ) const
630 return FindColor( aValue, myMin, myMax, myInterval, aColor );
634 Standard_Boolean Aspect_ColorScale::FindColor( const Standard_Real aValue,
635 const Standard_Real aMin,
636 const Standard_Real aMax,
637 const Standard_Integer ColorsCount,
638 Quantity_Color& aColor )
640 if( aValue<aMin || aValue>aMax || aMax<aMin )
641 return Standard_False;
645 Standard_Real IntervNumber = 0;
648 else if( aValue>aMax )
649 IntervNumber = ColorsCount-1;
650 else if( Abs( aMax-aMin ) > Precision::Approximation() )
651 IntervNumber = Ceiling( Standard_Real( ColorsCount ) * ( aValue - aMin ) / ( aMax - aMin ) );
653 Standard_Integer Interv = Standard_Integer( IntervNumber );
655 aColor = Quantity_Color( HueFromValue( Interv, 0, ColorsCount - 1 ), 1.0, 1.0, Quantity_TOC_HLS );
657 return Standard_True;