Salome HOME
Join modifications from branch OCC_debug_for_3_2_0b1
[modules/gui.git] / src / Qtx / QtxColorScale.cxx
1 // Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA 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/
18 //
19 // File:      QtxColorScale.cxx
20 // Author:    Sergey TELKOV
21
22 #include "QtxColorScale.h"
23
24 #include <qmap.h>
25 #include <qimage.h>
26 #include <qregexp.h>
27 #include <qpixmap.h>
28 #include <qbitmap.h>
29 #include <qpainter.h>
30 #include <qmainwindow.h>
31 #include <qstringlist.h>
32 #include <qstylesheet.h>
33 #include <qsimplerichtext.h>
34
35 #include <math.h>
36
37 /*!
38   Constructor
39 */
40 QtxColorScale::QtxColorScale( QWidget* parent, const char* name, WFlags f )
41 : QFrame( parent, name, f | WResizeNoErase | WRepaintNoErase ),
42 myDock( 0 ),
43 myMin( 0.0 ),
44 myMax( 1.0 ),
45 myTitle( "" ),
46 myInterval( 10 ),
47 myStyleSheet( 0 ),
48 myFormat( "%.4g" ),
49 myColorMode( Auto ),
50 myLabelMode( Auto ),
51 myLabelPos( Right ),
52 myTitlePos( Center ),
53 myDumpMode( NoDump ),
54 myFlags( AtBorder | WrapTitle )
55 {
56         setCaption( tr ( "Color scale" ) );
57 }
58
59 /*!
60   Constructor
61 */
62 QtxColorScale::QtxColorScale( const int num, QWidget* parent, const char* name, WFlags f )
63 : QFrame( parent, name, f | WResizeNoErase | WRepaintNoErase ),
64 myDock( 0 ),
65 myMin( 0.0 ),
66 myMax( 1.0 ),
67 myTitle( "" ),
68 myInterval( num ),
69 myStyleSheet( 0 ),
70 myFormat( "%.4g" ),
71 myColorMode( Auto ),
72 myLabelMode( Auto ),
73 myLabelPos( Right ),
74 myTitlePos( Center ),
75 myDumpMode( NoDump ),
76 myFlags( AtBorder | WrapTitle )
77 {
78         setCaption( tr ( "Color scale" ) );
79 }
80
81 #if QT_VER == 3
82
83 /*!
84   Constructor
85 */
86 QtxColorScale::QtxColorScale( Dock* dock, const char* name, WFlags f )
87 : QFrame( dock, name, f | WResizeNoErase | WRepaintNoErase ),
88 myMin( 0.0 ),
89 myMax( 1.0 ),
90 myTitle( "" ),
91 myDock( dock ),
92 myInterval( 10 ),
93 myStyleSheet( 0 ),
94 myFormat( "%.4g" ),
95 myColorMode( Auto ),
96 myLabelMode( Auto ),
97 myLabelPos( Right ),
98 myTitlePos( Center ),
99 myDumpMode( NoDump ),
100 myFlags( AtBorder | WrapTitle )
101 {
102         setCaption( tr ( "Color scale" ) );
103 }
104
105 #endif
106
107 /*!
108   Destructor
109 */
110 QtxColorScale::~QtxColorScale()
111 {
112 }
113
114 /*!
115   \returns minimal limit of scale.
116 */
117 double QtxColorScale::minimum() const
118 {
119         return myMin;
120 }
121
122 /*!
123   \return maximal limit of scale.
124 */
125 double QtxColorScale::maximum() const
126 {
127         return myMax;
128 }
129
130 /*!
131   \return range (minimal and maximal limits) of scale.
132 */
133 void QtxColorScale::range( double& min, double& max ) const
134 {
135         min = myMin;
136         max = myMax;
137 }
138
139 /*!
140   \return the current title string.
141 */
142 QString QtxColorScale::title() const
143 {
144         return myTitle;
145 }
146
147 /*!
148   \returns the current format of number presentation in labels for Auto label mode (sprintf specification).
149 */
150 QString QtxColorScale::format() const
151 {
152         return myFormat;
153 }
154
155 /*!
156   \return dump mode.
157 */
158 int QtxColorScale::dumpMode() const
159 {
160         return myDumpMode;
161 }
162
163 /*!
164   \return label mode.
165 */
166 int QtxColorScale::labelMode() const
167 {
168         return myLabelMode;
169 }
170
171 /*!
172   \return color mode.
173 */
174 int QtxColorScale::colorMode() const
175 {
176         return myColorMode;
177 }
178
179 /*!
180   \return intervals number of color scale.
181 */
182 int QtxColorScale::intervalsNumber() const
183 {
184         return myInterval;
185 }
186
187 /*!
188   \return the user label of specified interval.
189 */
190 QString QtxColorScale::label( const int idx ) const
191 {
192         QString res;
193         if ( idx >= 0 && idx < (int)myLabels.count() )
194                 res = *myLabels.at( idx );
195         return res;
196 }
197
198 /*!
199   \return the user color of specified interval.
200 */
201 QColor QtxColorScale::color( const int idx ) const
202 {
203         QColor res;
204         if ( idx >= 0 && idx < (int)myColors.count() )
205                 res = *myColors.at( idx );
206         return res;
207 }
208
209 /*!
210   \return the user labels.
211 */
212 void QtxColorScale::labels( QStringList& list ) const
213 {
214         list = myLabels;
215 }
216
217 /*!
218   \return the user color.
219 */
220 void QtxColorScale::colors( QValueList<QColor>& list ) const
221 {
222         list = myColors;
223 }
224
225 /*!
226   \return the label position.
227 */
228 int QtxColorScale::labelPosition() const
229 {
230         return myLabelPos;
231 }
232
233 /*!
234   \return the title position.
235 */
236 int QtxColorScale::titlePosition() const
237 {
238         return myTitlePos;
239 }
240
241 /*!
242   Sets the minimum limit.
243 */
244 void QtxColorScale::setMinimum( const double val )
245 {
246         setRange( val, maximum() );
247 }
248
249 /*!
250   Sets the maximum limit.
251 */
252 void QtxColorScale::setMaximum( const double val )
253 {
254         setRange( minimum(), val );
255 }
256
257 /*!
258   Sets the minimum and maximum limits.
259 */
260 void QtxColorScale::setRange( const double min, const double max )
261 {
262         if ( myMin == min && myMax == max )
263                 return;
264
265         myMin = min;
266         myMax = max;
267
268         myPrecise = QString::null;
269
270         if ( colorMode() == Auto || labelMode() == Auto )
271                 updateScale();
272 }
273
274 /*!
275   Sets the title string.
276 */
277 void QtxColorScale::setTitle( const QString& str )
278 {
279         if ( myTitle == str )
280                 return;
281
282         myTitle = str;
283         updateScale();
284 }
285
286 /*!
287   Sets the format of number presentation in labels for
288   Auto label mode (sprintf specification).
289 */
290 void QtxColorScale::setFormat( const QString& format )
291 {
292         if ( myFormat == format )
293                 return;
294
295         myFormat = format;
296         myPrecise = QString::null;
297         if ( colorMode() == Auto )
298                 updateScale();
299 }
300
301 /*!
302   Sets the number of intervals.
303 */
304 void QtxColorScale::setIntervalsNumber( const int num )
305 {
306         if ( myInterval == num || num < 1 )
307                 return;
308
309         myInterval = num;
310         myPrecise = QString::null;
311
312         updateScale();
313 }
314
315 /*!
316   Sets the user label for specified interval. If number
317   of interval is negative then user label will be added
318   as new at the end of list.
319 */
320 void QtxColorScale::setLabel( const QString& txt, const int idx )
321 {
322         bool changed = false;
323         uint i = idx < 0 ? myLabels.count() : idx;
324         if ( i < myLabels.count() )
325         {
326                 changed = *myLabels.at( i ) != txt;
327                 myLabels[i] = txt;
328         }
329         else
330         {
331                 changed = true;
332                 while ( i >= myLabels.count() )
333                     myLabels.append( "" );
334                 myLabels[i] = txt;
335         }
336         if ( changed )
337                 updateScale();
338 }
339
340 /*!
341   Sets the user color for specified interval. If number
342   of interval is negative then user color will be added
343   as new at the end of list.
344 */
345 void QtxColorScale::setColor( const QColor& clr, const int idx )
346 {
347         bool changed = false;
348         uint i = idx < 0 ? myColors.count() : idx;
349         if ( i < myColors.count() )
350         {
351                 changed = *myColors.at( i ) != clr;
352                 myColors[i] = clr;
353         }
354         else
355         {
356                 changed = true;
357         while ( i >= myColors.count() )
358             myColors.append( QColor() );
359                 myColors[i] = clr;
360         }
361         if ( changed )
362                 updateScale();
363 }
364
365 /*!
366   Replace the all user label with specified list.
367 */
368 void QtxColorScale::setLabels( const QStringList& list )
369 {
370         if ( list.isEmpty() )
371                 return;
372
373         myLabels = list;
374         updateScale();
375 }
376
377 /*!
378   Replace the all user colors with specified list.
379 */
380 void QtxColorScale::setColors( const QValueList<QColor>& list )
381 {
382         if ( list.isEmpty() )
383             return;
384
385         myColors = list;
386         updateScale();
387 }
388
389 /*!
390   Sets the color mode (Auto or User).
391 */
392 void QtxColorScale::setColorMode( const int mode )
393 {
394         if ( myColorMode == mode )
395                 return;
396
397         myColorMode = mode;
398         updateScale();
399 }
400
401 /*!
402   Sets the dump mode.
403 */
404 void QtxColorScale::setDumpMode( const int mode )
405 {
406         myDumpMode = mode;
407 }
408
409 /*!
410   Sets the label mode (Auto or User).
411 */
412 void QtxColorScale::setLabelMode( const int mode )
413 {
414         if ( myLabelMode != mode )
415         {
416                 myLabelMode = mode;
417                 updateScale();
418         }
419 }
420
421 /*!
422   Sets the label position.
423 */
424 void QtxColorScale::setLabelPosition( const int pos )
425 {
426         if ( myLabelPos != pos && pos >= None && pos <= Center )
427         {
428                 myLabelPos = pos;
429                 updateScale();
430         }
431 }
432
433 /*!
434   Sets the title position.
435 */
436 void QtxColorScale::setTitlePosition( const int pos )
437 {
438         if ( myTitlePos != pos && pos >= None && pos <= Center )
439         {
440                 myTitlePos = pos;
441                 updateScale();
442         }
443 }
444
445 /*!
446   Set the specified flags.
447 */
448 void QtxColorScale::setFlags( const int flags )
449 {
450         int prev = myFlags;
451         myFlags |= flags;
452         if ( prev != myFlags )
453                 updateScale();
454 }
455
456 /*!
457   \return true if specified flags are setted.
458 */
459 bool QtxColorScale::testFlags( const int flags ) const
460 {
461         return ( myFlags & flags ) == flags;
462 }
463
464 /*!
465   Clear (reset) the specified flags.
466 */
467 void QtxColorScale::clearFlags( const int flags )
468 {
469         int prev = myFlags;
470         myFlags &= ~flags;
471         if ( prev != myFlags )
472                 updateScale();
473 }
474
475 /*!
476   \return minimum size hint
477 */
478 QSize QtxColorScale::minimumSizeHint() const
479 {
480   QSize sz = calculateSize( true, myFlags, titlePosition() != None, labelPosition() != None, true );
481         return sz + QSize( frameWidth(), frameWidth() );
482 }
483
484 /*!
485   \return size hint
486 */
487 QSize QtxColorScale::sizeHint() const
488 {
489   QSize sz = calculateSize( false, myFlags, titlePosition() != None, labelPosition() != None, true );
490         return sz + QSize( frameWidth(), frameWidth() );
491 }
492
493 /*!
494   Dump color scale into pixmap with current size.
495 */
496 QSize QtxColorScale::calculateSize( const bool min, const int flags, const bool title,
497                                                                                     const bool labels, const bool colors ) const
498 {
499         int num = intervalsNumber();
500
501         int spacer = 5;
502         int textWidth = 0;
503         int textHeight = fontMetrics().height();
504         int colorWidth = 20;
505
506         if ( labels && colors )
507   {
508     QtxColorScale* that = (QtxColorScale*)this;
509     QString fmt = that->myFormat;
510
511                 for ( int idx = 0; idx < num; idx++ )
512                         textWidth = QMAX( textWidth, fontMetrics().width( getLabel( idx ) ) );
513
514     if ( !min )
515       that->myFormat = that->myFormat.replace( QRegExp( "g" ), "f" );
516
517                 for ( int index = 0; index < num; index++ )
518                         textWidth = QMAX( textWidth, fontMetrics().width( getLabel( index ) ) );
519
520     that->myFormat = fmt;
521   }
522
523         int scaleWidth = 0;
524         int scaleHeight = 0;
525
526         int titleWidth = 0;
527         int titleHeight = 0;
528
529         if ( flags & AtBorder )
530         {
531                 num++;
532                 if ( min && title && !myTitle.isEmpty() )
533                         titleHeight += 10;
534         }
535
536         if ( colors )
537         {
538                 scaleWidth = colorWidth + textWidth + ( textWidth ? 3 : 2 ) * spacer;
539                 if ( min )
540                         scaleHeight = QMAX( 2 * num, 3 * textHeight );
541                 else
542                         scaleHeight = (int)( 1.5 * ( num + 1 ) * textHeight );
543         }
544
545         if ( title )
546         {
547                 QSimpleRichText* srt = simpleRichText( flags );
548                 if ( srt )
549                 {
550                         QPainter p( this );
551                         if ( scaleWidth )
552                                 srt->setWidth( &p, scaleWidth );
553
554                         titleHeight = srt->height() + spacer;
555                         titleWidth = srt->widthUsed() + 10;
556
557                         delete srt;
558                 }
559         }
560
561         int W = QMAX( titleWidth, scaleWidth ) + width() - contentsRect().width();
562         int H = scaleHeight + titleHeight + height() - contentsRect().height();
563
564         return QSize( W, H );
565 }
566
567 /*!
568   Dump color scale into pixmap with current size.
569 */
570 QPixmap QtxColorScale::dump() const
571 {
572         QPixmap aPix;
573   
574         if ( dumpMode() != NoDump )
575         {
576                 aPix = QPixmap( size() );
577                 if ( !aPix.isNull() )
578                 {
579                         bool scale = ( myDumpMode == ScaleDump || myDumpMode == FullDump );
580                         bool label = ( myDumpMode == ScaleDump || myDumpMode == FullDump ) &&
581                                                  labelPosition() != None;
582                         bool title = ( myDumpMode == TitleDump || myDumpMode == FullDump ) &&
583                                                  titlePosition() != None;
584
585 #if QT_VER < 3
586             QColor bgc = backgroundColor();
587 #else
588             QColor bgc = paletteBackgroundColor();
589 #endif
590                         QPainter p;
591                         p.begin( &aPix );
592                         p.fillRect( 0, 0, aPix.width(), aPix.height(), bgc );
593                         drawScale( &p, bgc, false, 0, 0, aPix.width(), aPix.height(), title, label, scale );
594                         p.end();
595                 }
596         }
597
598         return aPix;
599 }
600
601 /*!
602   Dump color scale into pixmap with specified size.
603 */
604 QPixmap QtxColorScale::dump( const int w, const int h ) const
605 {
606 #if QT_VER < 3
607         return dump( backgroundColor(), w, h );
608 #else
609         return dump( paletteBackgroundColor(), w, h );
610 #endif
611 }
612
613 /*!
614   Dump color scale into pixmap with specified size and background color.
615 */
616 QPixmap QtxColorScale::dump( const QColor& bg, const int w, const int h ) const
617 {
618         QPixmap aPix;
619         if ( dumpMode() != NoDump )
620         {
621                 bool scale = ( myDumpMode == ScaleDump || myDumpMode == FullDump );
622                 bool label = ( myDumpMode == ScaleDump || myDumpMode == FullDump ) &&
623                                          labelPosition() != None;
624                 bool title = ( myDumpMode == TitleDump || myDumpMode == FullDump ) &&
625                                          titlePosition() != None;
626
627                 int W = w;
628                 int H = h;
629                 if ( W < 0 || H < 0 )
630                 {
631                         QSize sz = calculateSize( false, myFlags & ~WrapTitle, title, label, scale );
632
633                         if ( W < 0 )
634                                 W = sz.width();
635                         if ( H < 0 )
636                                 H = sz.height();
637                 }
638
639                 aPix = QPixmap( W, H );
640                 if ( !aPix.isNull() )
641                 {
642                         QPainter p;
643                         p.begin( &aPix );
644                         p.fillRect( 0, 0, aPix.width(), aPix.height(), bg );
645                         drawScale( &p, bg, false, 0, 0, aPix.width(), aPix.height(), title, label, scale );
646                         p.end();
647                 }
648         }
649
650         return aPix;
651 }
652
653 /*!
654   Show the color scale. [Reimplemented]
655 */
656 void QtxColorScale::show()
657 {
658 #if QT_VER == 3
659         if ( myDock )
660                 myDock->activate();
661         else
662 #endif
663         QFrame::show();
664 }
665
666 /*!
667   Hides the color scale. [Reimplemented]
668 */
669 void QtxColorScale::hide()
670 {
671 #if QT_VER == 3
672         if ( myDock )
673                 myDock->deactivate();
674         else
675 #endif
676         QFrame::hide();
677 }
678
679 /*!
680   Draw color scale contents. [Reimplemented]
681 */
682 void QtxColorScale::drawContents( QPainter* p )
683 {
684         if ( !isUpdatesEnabled() )
685                 return;
686
687         QRect aDrawRect = contentsRect();
688
689         drawScale( p, false/*testFlags( Transparent )*/, aDrawRect.x(),
690                            aDrawRect.y(), aDrawRect.width(), aDrawRect.height(),
691                            titlePosition() != None, labelPosition() != None, true );
692 }
693
694 /*!
695   Draw color scale contents.
696 */
697 void QtxColorScale::drawScale( QPainter* p, const bool transp, const int X, const int Y,
698                                const int W, const int H, const bool title,
699                                const bool label, const bool scale ) const
700 {
701         QPixmap cache( W, H );
702         QPainter cp( &cache );
703
704 #if QT_VER < 3
705         drawScale( &cp, backgroundColor(), transp, 0, 0, W, H, title, label, scale );
706 #else
707         drawScale( &cp, paletteBackgroundColor(), transp, 0, 0, W, H, title, label, scale );
708 #endif
709         cp.end();
710
711         p->drawPixmap( X, Y, cache );
712 }
713
714 /*!
715   Draw color scale contents.
716 */
717 void QtxColorScale::drawScale( QPainter* p, const QColor& bg, const bool transp,
718                                const int X, const int Y, const int W, const int H,
719                                const bool drawTitle, const bool drawLabel, const bool drawColors ) const
720 {
721         if ( !transp )
722                 p->fillRect( X, Y, W, H, bg );
723
724         int num = intervalsNumber();
725
726         int labPos = labelPosition();
727
728         int spacer = 5;
729         int textWidth = 0;
730         int textHeight = p->fontMetrics().height();
731
732         QString aTitle = title();
733
734         int titleWidth = 0;
735         int titleHeight = 0;
736
737         if ( qGray( bg.rgb() ) < 128 )
738                 p->setPen( QColor( 255, 255, 255 ) );
739         else
740             p->setPen( QColor( 0, 0, 0 ) );
741
742         // Draw title
743         if ( drawTitle )
744         {
745                 QSimpleRichText* srt = simpleRichText( myFlags );
746                 if ( srt )
747                 {
748                         srt->setWidth( p, W - 10 );
749                         titleHeight = srt->height() + spacer;
750                         titleWidth = srt->widthUsed();
751                         QColorGroup cg = colorGroup();
752                         cg.setColor( QColorGroup::Text, p->pen().color() );
753                         srt->draw( p, X + 5, Y, QRect( 0, 0, srt->width(), srt->height() ), cg );
754
755                         delete srt;
756                 }
757         }
758
759         bool reverse = testFlags( Reverse );
760
761         QValueList<QColor>  colors;
762         QValueList<QString> labels;
763         for ( int idx = 0; idx < num; idx++ )
764         {
765                 if ( reverse )
766                 {
767                         colors.append( getColor( idx ) );
768                         labels.append( getLabel( idx ) );
769                 }
770                 else
771                 {
772                         colors.prepend( getColor( idx ) );
773                         labels.prepend( getLabel( idx ) );
774                 }
775         }
776
777         if ( testFlags( AtBorder ) )
778         {
779                 if ( reverse )
780                         labels.append( getLabel( num ) );
781                 else
782                         labels.prepend( getLabel( num ) );
783                 if ( drawLabel )
784                         textWidth = QMAX( textWidth, p->fontMetrics().width( labels.last() ) );
785         }
786
787         if ( drawLabel )
788         {
789                 const QFontMetrics& fm = p->fontMetrics();
790                 for ( QStringList::ConstIterator it = labels.begin(); it != labels.end(); ++it )
791                         textWidth = QMAX( textWidth, fm.width( *it) );
792         }
793
794         int lab = labels.count();
795
796         double spc = ( H - ( ( QMIN( lab, 2 ) + QABS( lab - num - 1 ) ) * textHeight ) - titleHeight );
797         double val = spc != 0 ? 1.0 * ( lab - QMIN( lab, 2 ) ) * textHeight / spc : 0;
798         double iPart;
799         double fPart = modf( val, &iPart );
800         int filter = (int)iPart + ( fPart != 0 ? 1 : 0 );
801         filter = QMAX( filter, 1 );
802
803         double step = 1.0 * ( H - ( lab - num + QABS( lab - num - 1 ) ) * textHeight - titleHeight ) / num;
804
805         int ascent = p->fontMetrics().ascent();
806         int colorWidth = QMAX( 5, QMIN( 20, W - textWidth - 3 * spacer ) );
807         if ( labPos == Center || !drawLabel )
808                 colorWidth = W - 2 * spacer;
809
810         // Draw colors
811         int x = X + spacer;
812         switch ( labPos )
813         {
814         case Left:
815             x += textWidth + ( textWidth ? 1 : 0 ) * spacer;
816                 break;
817         }
818
819         double offset = 1.0 * textHeight / 2 * ( lab - num + QABS( lab - num - 1 ) ) + titleHeight;
820         QValueList<QColor>::Iterator cit = colors.begin();
821   uint ci = 0;
822         for ( ci = 0; cit != colors.end() && drawColors; ++cit, ci++ )
823         {
824                 int y = (int)( Y + ci * step + offset );
825                 int h = (int)( Y + ( ci + 1 ) * step + offset ) - y;
826                 p->fillRect( x, y, colorWidth, h, *cit );
827         }
828
829         if ( drawColors )
830                 p->drawRect( int( x - 1 ), int( Y + offset - 1 ), int( colorWidth + 2 ), int( ci * step + 2 ) );
831
832         // Draw labels
833         offset = 1.0 * QABS( lab - num - 1 ) * ( step - textHeight ) / 2 +
834                                                  1.0 * QABS( lab - num - 1 ) * textHeight / 2;
835         offset += titleHeight;
836         if ( drawLabel && !labels.isEmpty() )
837         {
838                 int i1 = 0;
839                 int i2 = lab - 1;
840                 int last1( i1 ), last2( i2 );
841                 int x = X + spacer;
842                 switch ( labPos )
843                 {
844                 case Center:
845                         x += ( colorWidth - textWidth ) / 2;
846                         break;
847                 case Right:
848                         x += colorWidth + spacer;
849                         break;
850                 }
851                 while ( i2 - i1 >= filter || ( i2 == 0 && i1 == 0 ) )
852                 {
853                         int pos1 = i1;
854                         int pos2 = lab - 1 - i2;
855                         if ( filter && !( pos1 % filter ) )
856                         {
857                                 p->drawText( x, (int)( Y + i1 * step + ascent + offset ), *labels.at( i1 ) );
858                                 last1 = i1;
859                         }
860                         if ( filter && !( pos2 % filter ) )
861                         {
862                                 p->drawText( x, (int)( Y + i2 * step + ascent + offset ), *labels.at( i2 ) );
863                                 last2 = i2;
864                         }
865                         i1++;
866                         i2--;
867                 }
868                 int pos = i1;
869                 int i0 = -1;
870                 while ( pos <= i2 && i0 == -1 )
871                 {
872                         if ( filter && !( pos % filter ) &&
873                                  QABS( pos - last1 ) >= filter && QABS( pos - last2 ) >= filter )
874                                 i0 = pos;
875                         pos++;
876                 }
877
878                 if ( i0 != -1 )
879                         p->drawText( x, (int)( Y + i0 * step + ascent + offset ), *labels.at( i0 ) );
880         }
881 }
882
883 /*!
884   \return the format for number labels.
885 */
886 QString QtxColorScale::getFormat() const
887 {
888         QString aFormat = format();
889
890         if ( !testFlags( PreciseFormat ) || testFlags( Integer ) )
891                 return aFormat;
892
893         if ( !myPrecise.isEmpty() )
894                 return myPrecise;
895
896         if ( aFormat.find( QRegExp( "^(%[0-9]*.?[0-9]*[fegFEG])$" ) ) != 0 )
897                 return aFormat;
898
899         int pos1 = aFormat.find( '.' );
900         int pos2 = aFormat.find( QRegExp( "[fegFEG]") );
901
902         QString aLocFormat;
903         int precision = 1;
904         if ( pos1 > 0 )
905         {
906                 aLocFormat = aFormat.mid( 0, pos1 + 1 );
907                 precision = aFormat.mid( pos1 + 1, pos2 - pos1 - 1 ).toInt();
908                 if ( precision < 1 )
909                         precision = 1;
910         }
911         else
912                 return aFormat;
913   
914         QtxColorScale* that = (QtxColorScale*)this;
915
916         // calculate format, maximum precision limited
917         // to 7 digits after the decimal point.
918         while ( myPrecise.isEmpty() && precision < 7 )
919         {
920                 QString aTmpFormat = aLocFormat;
921                 aTmpFormat += QString( "%1" ).arg( precision );
922                 aTmpFormat += aFormat.mid( pos2 );
923
924                 QMap<QString, int> map;
925                 bool isHasTwinz = false;
926
927                 for ( int idx = 0; idx < intervalsNumber() && !isHasTwinz; idx++ )
928                 {
929                         double val = getNumber( idx );
930                         QString tmpname = QString().sprintf( aTmpFormat, val );
931                         isHasTwinz = map.contains( tmpname );
932                         map.insert( tmpname, 1 );
933                 }
934
935                 if ( !isHasTwinz )
936                         that->myPrecise = aTmpFormat;
937                 precision++;
938         }
939
940         if ( !myPrecise.isEmpty() )
941                 aFormat = myPrecise;
942
943         return aFormat;
944 }
945
946 /*!
947   \return the number for specified interval.
948 */
949 double QtxColorScale::getNumber( const int idx ) const
950 {
951         double val = 0;
952         if ( intervalsNumber() > 0 )
953                 val = minimum() + idx * ( QABS( maximum() - minimum() ) / intervalsNumber() );
954         return val;
955 }
956
957 /*!
958   \return the label for specified interval according to the current label mode.
959 */
960 QString QtxColorScale::getLabel( const int idx ) const
961 {
962         QString res;
963         if ( labelMode() == User )
964                 res = label( idx );
965         else
966         {
967                 double val = getNumber( idx );
968                 res = QString().sprintf( getFormat(), testFlags( Integer ) ? (int)val : val );
969         }
970         return res;
971 }
972
973 /*!
974   \return the color for specified interval according to the current color mode.
975 */
976 QColor QtxColorScale::getColor( const int idx ) const
977 {
978         QColor res;
979         if ( colorMode() == User )
980                 res = color( idx );
981         else
982     res = Qtx::scaleColor( idx, 0, intervalsNumber() - 1 );
983         return res;
984 }
985
986 /*!
987   Update color scale if it required.
988 */
989 void QtxColorScale::updateScale()
990 {
991   update();
992         updateGeometry();
993 }
994
995 /*!
996   \return QSimpleRichText object for title. If title
997   not defined (empty string) then return null pointer.
998   Object should be deleted by caller function.
999 */
1000 QSimpleRichText* QtxColorScale::simpleRichText( const int flags ) const
1001 {
1002         QSimpleRichText* srt = 0;
1003
1004         QString aTitle;
1005         switch ( titlePosition() )
1006         {
1007         case Left:
1008                 aTitle = QString( "<p align=\"left\">%1</p>" );
1009                 break;
1010         case Right:
1011                 aTitle = QString( "<p align=\"right\">%1</p>" );
1012                 break;
1013         case Center:
1014                 aTitle = QString( "<p align=\"center\">%1</p>" );
1015                 break;
1016         case None:
1017         default:
1018                 break;
1019         }
1020
1021         if ( !aTitle.isEmpty() && !title().isEmpty() )
1022         {
1023                 if ( !myStyleSheet )
1024                 {
1025                         QtxColorScale* that = (QtxColorScale*)this;
1026                         that->myStyleSheet = new QStyleSheet( that );
1027                 }
1028
1029                 if ( myStyleSheet )
1030                 {
1031                         QStyleSheetItem* item = myStyleSheet->item( "p" );
1032                         if ( item )
1033                                 item->setWhiteSpaceMode( flags & WrapTitle ? QStyleSheetItem::WhiteSpaceNormal :
1034                                                                                                                      QStyleSheetItem::WhiteSpaceNoWrap );
1035                 }
1036
1037                 aTitle = aTitle.arg( title() );
1038                 srt = new QSimpleRichText( aTitle, font(), QString::null, myStyleSheet );
1039         }
1040
1041         return srt;
1042 }
1043
1044 #if QT_VER == 3
1045
1046 /*!
1047   \class QtxColorScale::Dock
1048   Dockable window contains the color scale.
1049 */
1050
1051 /*!
1052   Constructor
1053 */
1054 QtxColorScale::Dock::Dock( Place p, QWidget* parent, const char* name, WFlags f )
1055 : QDockWindow( p, parent, name, f ),
1056 myBlockShow( false ),
1057 myBlockResize( false )
1058 {
1059         myScale = new QtxColorScale( this );
1060
1061         setWidget( myScale );
1062
1063         setCloseMode( Always );
1064         setMovingEnabled( true );
1065         setResizeEnabled( true );
1066         setHorizontalStretchable( false );
1067
1068         setCaption( tr ( "Color scale" ) );
1069 }
1070
1071 /*!
1072   Destructor.
1073 */
1074 QtxColorScale::Dock::~Dock()
1075 {
1076 }
1077
1078 /*!
1079   \return color scale widget.
1080 */
1081 QtxColorScale* QtxColorScale::Dock::colorScale() const
1082 {
1083         return myScale;
1084 }
1085
1086 /*!
1087   Set the dockable window is visible for main window.
1088 */
1089 void QtxColorScale::Dock::activate()
1090 {
1091         if ( myBlockShow )
1092                 return;
1093
1094         QMainWindow* mw = 0;
1095         QWidget* p = parentWidget();
1096         while ( !mw && p )
1097         {
1098                 if ( p->inherits( "QMainWindow" ) )
1099                         mw = (QMainWindow*)p;
1100                 p = p->parentWidget();
1101         }
1102         if ( mw )
1103                 mw->setAppropriate( this, true );
1104 }
1105
1106 /*!
1107   Set the dockable window is hidden for main window.
1108 */
1109 void QtxColorScale::Dock::deactivate()
1110 {
1111         if ( myBlockShow )
1112                 return;
1113
1114         QMainWindow* mw = 0;
1115         QWidget* p = parentWidget();
1116         while ( !mw && p )
1117         {
1118                 if ( p->inherits( "QMainWindow" ) )
1119                         mw = (QMainWindow*)p;
1120                 p = p->parentWidget();
1121         }
1122         if ( mw )
1123                 mw->setAppropriate( this, false );
1124 }
1125
1126 /*!
1127   \return true if the dockable window is visible.
1128 */
1129 bool QtxColorScale::Dock::isActive() const
1130 {
1131         QMainWindow* mw = 0;
1132         QWidget* p = parentWidget();
1133         while ( !mw && p )
1134         {
1135                 if ( p->inherits( "QMainWindow" ) )
1136                         mw = (QMainWindow*)p;
1137                 p = p->parentWidget();
1138         }
1139         if ( mw )
1140                 return mw->appropriate( (QDockWindow*)this );
1141         else
1142                 return false;
1143 }
1144
1145 /*!
1146   Redefined show
1147 */
1148 void QtxColorScale::Dock::show()
1149 {
1150         bool f = myBlockShow;
1151         myBlockShow = true;
1152         QDockWindow::show();
1153         myBlockShow = f;
1154 }
1155
1156 /*!
1157   Redefined hide
1158 */
1159 void QtxColorScale::Dock::hide()
1160 {
1161         bool f = myBlockShow;
1162         myBlockShow = false;
1163         QDockWindow::hide();
1164         myBlockShow = f;
1165 }
1166
1167 /*!
1168   Make extent width as maximum value of widget width.
1169 */
1170 void QtxColorScale::Dock::resize( int w, int h )
1171 {
1172         QDockWindow::resize( w, h );
1173
1174         if ( myBlockResize )
1175                 return;
1176
1177         if ( orientation() == Qt::Vertical )
1178                 setFixedExtentWidth( QMAX( fixedExtent().width(), w ) );
1179         else if ( orientation() == Qt::Horizontal )
1180                 setFixedExtentHeight( QMAX( fixedExtent().height(), h ) );
1181 }
1182
1183 /*!
1184   Set orientation
1185   \param o - new orientation
1186 */
1187 void QtxColorScale::Dock::setOrientation( Orientation o )
1188 {
1189         bool b = myBlockResize;
1190         myBlockResize = true;
1191         QDockWindow::setOrientation( o );
1192         myBlockResize = b;
1193 }
1194
1195 #endif