Salome HOME
Implement generic "Dump view" method to be used by all views (toolbar & context menu)
[modules/gui.git] / src / Plot2d / Plot2d_ViewFrame.cxx
1 #include "Plot2d_ViewFrame.h"
2
3 #include "Plot2d_Prs.h"
4 #include "Plot2d_Curve.h"
5 #include "Plot2d_FitDataDlg.h"
6 #include "Plot2d_ViewWindow.h"
7 #include "Plot2d_SetupViewDlg.h"
8
9 #include "SUIT_Tools.h"
10 #include "SUIT_Session.h"
11 #include "SUIT_MessageBox.h"
12 #include "SUIT_ResourceMgr.h"
13 #include "SUIT_Application.h"
14
15 //#include "utilities.h"
16
17 #include "qapplication.h"
18 #include <qtoolbar.h>
19 #include <qtoolbutton.h>
20 #include <qcursor.h>
21 #include <qcolordialog.h>
22 #include <qptrlist.h>
23 #include <qlayout.h>
24 #include <qmap.h>
25
26 #include <qwt_math.h>
27 #include <qwt_plot_canvas.h>
28 #include <iostream.h>
29 #include <stdlib.h>
30
31 //#include "utilities.h"
32
33 #define DEFAULT_LINE_WIDTH     0     // (default) line width
34 #define DEFAULT_MARKER_SIZE    9     // default marker size
35 #define MIN_RECT_SIZE          11    // min sensibility area size
36
37 const char* imageZoomCursor[] = { 
38 "32 32 3 1",
39 ". c None",
40 "a c #000000",
41 "# c #ffffff",
42 "................................",
43 "................................",
44 ".#######........................",
45 "..aaaaaaa.......................",
46 "................................",
47 ".............#####..............",
48 "...........##.aaaa##............",
49 "..........#.aa.....a#...........",
50 ".........#.a.........#..........",
51 ".........#a..........#a.........",
52 "........#.a...........#.........",
53 "........#a............#a........",
54 "........#a............#a........",
55 "........#a............#a........",
56 "........#a............#a........",
57 ".........#...........#.a........",
58 ".........#a..........#a.........",
59 ".........##.........#.a.........",
60 "........#####.....##.a..........",
61 ".......###aaa#####.aa...........",
62 "......###aa...aaaaa.......#.....",
63 ".....###aa................#a....",
64 "....###aa.................#a....",
65 "...###aa...............#######..",
66 "....#aa.................aa#aaaa.",
67 ".....a....................#a....",
68 "..........................#a....",
69 "...........................a....",
70 "................................",
71 "................................",
72 "................................",
73 "................................"};
74
75 const char* imageCrossCursor[] = { 
76   "32 32 3 1",
77   ". c None",
78   "a c #000000",
79   "# c #ffffff",
80   "................................",
81   "................................",
82   "................................",
83   "................................",
84   "................................",
85   "................................",
86   "................................",
87   "...............#................",
88   "...............#a...............",
89   "...............#a...............",
90   "...............#a...............",
91   "...............#a...............",
92   "...............#a...............",
93   "...............#a...............",
94   "...............#a...............",
95   ".......#################........",
96   "........aaaaaaa#aaaaaaaaa.......",
97   "...............#a...............",
98   "...............#a...............",
99   "...............#a...............",
100   "...............#a...............",
101   "...............#a...............",
102   "...............#a...............",
103   "...............#a...............",
104   "................a...............",
105   "................................",
106   "................................",
107   "................................",
108   "................................",
109   "................................",
110   "................................",
111   "................................"};
112   
113
114 QPixmap zoomPixmap(imageZoomCursor);
115 QPixmap globalPanPixmap(imageCrossCursor);
116
117 QCursor panCursor(Qt::SizeAllCursor);
118 QCursor zoomCursor(zoomPixmap);
119 QCursor glPanCursor(globalPanPixmap);
120
121 //=================================================================================
122 // Plot2d_ViewFrame implementation
123 //=================================================================================
124
125 /*!
126   Constructor
127 */
128 Plot2d_ViewFrame::Plot2d_ViewFrame( QWidget* parent, const QString& title )
129      : QWidget (parent, title, 0),
130        myOperation( NoOpId ), 
131        myCurveType( 1 ), 
132        myShowLegend( true ), myLegendPos( 1 ),
133        myMarkerSize( DEFAULT_MARKER_SIZE ),
134        myTitle( "" ), myXTitle( "" ), myYTitle( "" ), myY2Title( "" ),
135        myBackground( white ),
136        myTitleEnabled( true ), myXTitleEnabled( true ),
137        myYTitleEnabled( true ), myY2TitleEnabled (true),
138        myXGridMajorEnabled( true ), myYGridMajorEnabled( true ), myY2GridMajorEnabled( true ), 
139        myXGridMinorEnabled( false ), myYGridMinorEnabled( false ), myY2GridMinorEnabled( false ),
140        myXGridMaxMajor( 8 ), myYGridMaxMajor( 8 ), myY2GridMaxMajor( 8 ),
141        myXGridMaxMinor( 5 ), myYGridMaxMinor( 5 ), myY2GridMaxMinor( 5 ),
142        myXMode( 0 ), myYMode( 0 ), mySecondY( false )
143 {
144   /* Plot 2d View */
145   QVBoxLayout* aLayout = new QVBoxLayout( this ); 
146   myPlot = new Plot2d_Plot2d( this );
147   aLayout->addWidget( myPlot );
148
149 //  createActions();
150
151   connect( myPlot, SIGNAL( plotMouseMoved( const QMouseEvent& ) ),
152      this,   SLOT( plotMouseMoved( const QMouseEvent& ) ) );
153   connect( myPlot, SIGNAL( plotMousePressed( const QMouseEvent& ) ),
154      this,   SLOT( plotMousePressed( const QMouseEvent& ) ) );
155   connect( myPlot, SIGNAL( plotMouseReleased( const QMouseEvent& ) ),
156      this,   SLOT( plotMouseReleased( const QMouseEvent& ) ) );
157   //connect( myPlot, SIGNAL( legendClicked( long ) ),
158   //   this,   SLOT( onLegendClicked( long ) ) );
159
160   /* Initial Setup - get from the preferences */
161   readPreferences();
162
163   myPlot->setMargin( 5 );
164   setCurveType( myCurveType, false );
165   setXGrid( myXGridMajorEnabled, myXGridMaxMajor, myXGridMinorEnabled, myXGridMaxMinor, false );
166   setYGrid( myYGridMajorEnabled, myYGridMaxMajor, myYGridMinorEnabled, myYGridMaxMinor,
167             myY2GridMajorEnabled, myY2GridMaxMajor, myY2GridMinorEnabled, myY2GridMaxMinor, false );
168
169   setTitle( myTitleEnabled,  myTitle,  MainTitle, false );
170   setTitle( myXTitleEnabled, myXTitle, XTitle, false );
171   setTitle( myYTitleEnabled, myYTitle, YTitle, false );
172
173   if (mySecondY)
174     setTitle( myY2TitleEnabled, myY2Title, Y2Title, false );
175   setHorScaleMode( myXMode, false );
176   setVerScaleMode( myYMode, false );
177   setBackgroundColor( myBackground );
178   setLegendPos( myLegendPos );
179   showLegend( myShowLegend, false );
180   myPlot->replot();
181
182   if ( parent ) {
183     resize( (int)(0.8 * parent->width()), (int)(0.8 * parent->height()) );
184   }
185   QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
186   QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
187   myXDistance = xMap.d2() - xMap.d1();
188   myYDistance = yMap.d2() - yMap.d1();
189   myYDistance2 = 0;
190   if (mySecondY) {
191     QwtDiMap yMap2 = myPlot->canvasMap( QwtPlot::yRight );
192     myYDistance2 = yMap2.d2() - yMap2.d1();
193   }
194 }
195 /*!
196   Destructor
197 */
198 Plot2d_ViewFrame::~Plot2d_ViewFrame()
199 {
200 }
201 /*!
202   Gets window's central widget
203 */
204 QWidget* Plot2d_ViewFrame::getViewWidget()
205 {
206   return (QWidget*)myPlot;
207 }
208 /*!
209   Actually this method just re-displays all curves which are presented in the viewer
210 */
211 void Plot2d_ViewFrame::DisplayAll()
212 {
213   QList<Plot2d_Curve> clist;
214   getCurves( clist );
215   for ( int i = 0; i < (int)clist.count(); i++ ) {
216     updateCurve( clist.at( i ), false );
217   }
218   myPlot->replot();
219 }
220 /*!
221    Removes all curves from the view
222 */
223 void Plot2d_ViewFrame::EraseAll() 
224 {
225   myPlot->clear();
226   myCurves.clear();
227   myPlot->replot();
228 }
229 /*!
230   Redraws viewframe contents
231 */
232 void Plot2d_ViewFrame::Repaint()
233 {
234   myPlot->replot();
235 }
236 /*!
237   Display presentation
238 */
239 void Plot2d_ViewFrame::Display( const Plot2d_Prs* prs )
240 {
241   if ( !prs || prs->IsNull() )
242     return;
243
244   if (prs->isSecondY()) {
245     myPlot->enableAxis(QwtPlot::yRight, true);
246     mySecondY = true;
247   }
248   else {
249     myPlot->enableAxis(QwtPlot::yRight, false);
250     mySecondY = false;
251   }
252
253   // display all curves from presentation
254   curveList aCurves = prs->getCurves();
255   displayCurves( aCurves );
256   setXGrid( myXGridMajorEnabled, myXGridMaxMajor, myXGridMinorEnabled, myXGridMaxMinor, true );
257   setYGrid( myYGridMajorEnabled, myYGridMaxMajor, myYGridMinorEnabled, myYGridMaxMinor,
258             myY2GridMajorEnabled, myY2GridMaxMajor, myY2GridMinorEnabled, myY2GridMaxMinor, true );
259 }
260
261 /*!
262   Erase presentation
263 */
264 void Plot2d_ViewFrame::Erase( const Plot2d_Prs* prs, const bool )
265 {
266   if ( !prs || prs->IsNull() )
267     return;
268
269   // erase all curves from presentation
270   curveList aCurves = prs->getCurves();
271   eraseCurves( aCurves );
272 }
273
274 /*!
275   Sets title
276 */
277 void Plot2d_ViewFrame::setTitle( const QString& title )
278 {
279   setTitle( myTitleEnabled, title, MainTitle, true );
280 }
281
282 /*!
283   Reads Plot2d view settings from the preferences
284 */
285 void Plot2d_ViewFrame::readPreferences()
286 {
287   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
288
289   myCurveType = resMgr->integerValue( "Plot2d", "CurveType", myCurveType );
290   if ( myCurveType < 1 || myCurveType > 2 )
291     myCurveType = 1;
292   myShowLegend = resMgr->booleanValue( "Plot2d", "ShowLegend", myShowLegend );
293   myLegendPos = resMgr->integerValue( "Plot2d", "LegendPos", myLegendPos );
294   myMarkerSize = resMgr->integerValue( "Plot2d", "MarkerSize", myMarkerSize );
295   myBackground = resMgr->colorValue( "Plot2d", "Background", myBackground );
296
297   myTitleEnabled = resMgr->booleanValue( "Plot2d", "ShowTitle", myTitleEnabled );
298   myXTitleEnabled = resMgr->booleanValue( "Plot2d", "ShowHorTitle", myXTitleEnabled );
299   myYTitleEnabled = resMgr->booleanValue( "Plot2d", "ShowVerLeftTitle", myYTitleEnabled );
300   myY2TitleEnabled = resMgr->booleanValue( "Plot2d", "ShowVerRightTitle", myY2TitleEnabled );
301
302   myXGridMajorEnabled = resMgr->booleanValue( "Plot2d", "EnableHorMajorGrid", myXGridMajorEnabled );
303   myYGridMajorEnabled = resMgr->booleanValue( "Plot2d", "EnableVerMajorGrid", myYGridMajorEnabled );
304   myY2GridMajorEnabled = resMgr->booleanValue( "Plot2d", "EnableRightVerMajorGrid", myY2GridMajorEnabled );
305
306   myXGridMinorEnabled = resMgr->booleanValue( "Plot2d", "EnableHorMinorGrid", myXGridMinorEnabled );
307   myYGridMinorEnabled = resMgr->booleanValue( "Plot2d", "EnableVerMinorGrid", myYGridMinorEnabled );
308   myY2GridMinorEnabled = resMgr->booleanValue( "Plot2d", "EnableRightVerMinorGrid", myY2GridMinorEnabled );
309
310   myXGridMaxMajor = resMgr->integerValue( "Plot2d", "HorMajorGridMax", myXGridMaxMajor );
311   myYGridMaxMajor = resMgr->integerValue( "Plot2d", "VerMajorGridMax", myYGridMaxMajor );
312   if ( mySecondY )
313     myY2GridMaxMajor = resMgr->integerValue( "Plot2d", "VerMajorRightGridMax", myY2GridMaxMajor );
314
315   myXGridMaxMinor = resMgr->integerValue( "Plot2d", "HorMinorGridMax", myXGridMaxMinor );
316   myYGridMaxMinor = resMgr->integerValue( "Plot2d", "VerMinorGridMax", myYGridMaxMinor );
317   if ( mySecondY )
318     myY2GridMaxMinor = resMgr->integerValue( "Plot2d", "VerMinorGridMax", myY2GridMaxMinor );
319
320   myXMode = resMgr->integerValue( "Plot2d", "HorScaleMode", myXMode );
321   myXMode = QMAX( 0, QMIN( 1, myXMode ) );
322
323   myYMode = resMgr->integerValue( "Plot2d", "VerScaleMode", myYMode );
324   myYMode = QMAX( 0, QMIN( 1, myYMode ) );
325 }
326
327 /*!
328   Writes Plot2d view settings to the preferences
329 */
330 void Plot2d_ViewFrame::writePreferences()
331 {
332   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
333
334   resMgr->setValue( "Plot2d", "CurveType", myCurveType );
335   resMgr->setValue( "Plot2d", "ShowLegend", myShowLegend );
336   resMgr->setValue( "Plot2d", "LegendPos", myLegendPos );
337   resMgr->setValue( "Plot2d", "MarkerSize", myMarkerSize );
338   resMgr->setValue( "Plot2d", "Background", myBackground );
339   resMgr->setValue( "Plot2d", "ShowTitle", myTitleEnabled );
340   resMgr->setValue( "Plot2d", "ShowHorTitle", myXTitleEnabled );
341   resMgr->setValue( "Plot2d", "ShowVerLeftTitle", myYTitleEnabled );
342   if ( mySecondY )
343     resMgr->setValue( "Plot2d", "ShowVerRightTitle", myY2TitleEnabled );
344
345   resMgr->setValue( "Plot2d", "EnableHorMajorGrid", myXGridMajorEnabled );
346   resMgr->setValue( "Plot2d", "EnableVerMajorGrid", myYGridMajorEnabled );
347   resMgr->setValue( "Plot2d", "EnableHorMinorGrid", myXGridMinorEnabled );
348   resMgr->setValue( "Plot2d", "EnableVerMinorGrid", myYGridMinorEnabled );
349
350   resMgr->setValue( "Plot2d", "HorMajorGridMax", myXGridMaxMajor );
351   resMgr->setValue( "Plot2d", "VerMajorGridMax", myYGridMaxMajor );
352
353   resMgr->setValue( "Plot2d", "HorMinorGridMax", myXGridMaxMinor );
354   resMgr->setValue( "Plot2d", "VerMinorGridMax", myYGridMaxMinor );
355
356   resMgr->setValue( "Plot2d", "HorScaleMode", myXMode );
357
358   if ( mySecondY )
359   {
360     resMgr->setValue( "Plot2d", "EnableRightVerMajorGrid", myY2GridMajorEnabled );
361     resMgr->setValue( "Plot2d", "EnableRightVerMinorGrid", myY2GridMinorEnabled );
362     resMgr->setValue( "Plot2d", "VerRightMajorGridMax", myY2GridMaxMajor );
363     resMgr->setValue( "Plot2d", "VerRightMinorGridMax", myY2GridMaxMinor );
364   }
365
366   resMgr->setValue( "Plot2d", "VerScaleMode", myYMode );
367 }
368
369 /*!
370   Prints mouse cursor coordinates into string
371 */
372 QString Plot2d_ViewFrame::getInfo( const QPoint& pnt ) 
373 {
374   int i;
375   bool xFound = false, yFound = false;
376   double xCoord, yCoord;
377   const QwtScaleDiv* aXscale = myPlot->axisScale( QwtPlot::xBottom );
378   for ( i = 0; i < aXscale->majCnt(); i++ ) {
379     double majXmark = aXscale->majMark( i );
380     int xmark = myPlot->transform( QwtPlot::xBottom, majXmark );
381     if ( xmark-2 == pnt.x() ) {
382       xCoord = majXmark; 
383       xFound = true;
384 //      MESSAGE("Plot2d_ViewFrame::getInfo : close maj X mark("<<i<<") = "<<majXmark<<" "<<xmark<<" "<<pnt.x());
385       break;
386     }
387   }
388   if ( !xFound ) {
389     for ( i = 0; i < aXscale->minCnt(); i++ ) {
390       double minXmark = aXscale->minMark( i );
391       int xmark = myPlot->transform( QwtPlot::xBottom, minXmark );
392       if ( xmark-2 == pnt.x() ) {
393         xCoord = minXmark; 
394         xFound = true;
395 //        MESSAGE("Plot2d_ViewFrame::getInfo : close min X mark("<<i<<") = "<<minXmark<<" "<<xmark<<" "<<pnt.x());
396         break;
397       }
398     }
399   }  
400   const QwtScaleDiv* aYscale = myPlot->axisScale( QwtPlot::yLeft );
401   for ( i = 0; i < aYscale->majCnt(); i++ ) {
402     double majYmark = aYscale->majMark( i );
403     int ymark = myPlot->transform( QwtPlot::yLeft, majYmark );
404     if ( ymark-2 == pnt.y() ) {
405       yCoord = majYmark; 
406       yFound = true;
407       break;
408     }
409   }
410   if ( !yFound ) {
411     for ( i = 0; i < aYscale->minCnt(); i++ ) {
412       double minYmark = aYscale->minMark( i );
413       int ymark = myPlot->transform( QwtPlot::yLeft, minYmark );
414       if ( ymark-2 == pnt.y() ) {
415         yCoord = minYmark; 
416         yFound = true;
417         break;
418       }
419     }
420   }  
421
422   QString strX = QString::number( xFound ? xCoord : myPlot->invTransform( QwtPlot::xBottom, pnt.x() ) ).stripWhiteSpace();
423   if ( strX == "-0" )
424     strX = "0";
425   QString strY = QString::number( yFound ? yCoord : myPlot->invTransform( QwtPlot::yLeft, pnt.y() ) ).stripWhiteSpace();
426   if ( strY == "-0" )
427     strY = "0";
428   QString info = "";
429
430   if (mySecondY) {
431     bool yFound2 = false;
432     double yCoord2;
433
434     const QwtScaleDiv* aYscale2 = myPlot->axisScale( QwtPlot::yRight );
435     for ( i = 0; i < aYscale2->majCnt(); i++ ) {
436       double majYmark = aYscale2->majMark( i );
437       int ymark = myPlot->transform( QwtPlot::yRight, majYmark );
438       if ( ymark-2 == pnt.y() ) {
439         yCoord2 = majYmark; 
440         yFound2 = true;
441         break;
442       }
443     }
444     if ( !yFound2 ) {
445       for ( i = 0; i < aYscale2->minCnt(); i++ ) {
446         double minYmark = aYscale2->minMark( i );
447         int ymark = myPlot->transform( QwtPlot::yRight, minYmark );
448         if ( ymark-2 == pnt.y() ) {
449           yCoord2 = minYmark; 
450           yFound2 = true;
451           break;
452         }
453       }
454     }
455     QString strY2 = QString::number( yFound2 ? yCoord2 : 
456                       myPlot->invTransform( QwtPlot::yRight, pnt.y() ) ).stripWhiteSpace();
457     if ( strY2 == "-0" )
458     strY2 = "0";
459     info = tr("INF_COORDINATES_SOME_Y").arg( strX ).arg( strY ).arg( strY2 );
460   }
461   else
462     info = tr("INF_COORDINATES").arg( strX ).arg( strY );
463
464   return info;
465 }
466
467 /*!
468   Converts Plot2d_Curve's marker style to Qwt marker style [ static ]
469 */
470 static QwtSymbol::Style plot2qwtMarker( Plot2d_Curve::MarkerType m )
471 {
472   QwtSymbol::Style ms = QwtSymbol::None;  
473   switch ( m ) {
474   case Plot2d_Curve::Circle:
475     ms = QwtSymbol::Ellipse;   break;
476   case Plot2d_Curve::Rectangle:
477     ms = QwtSymbol::Rect;      break;
478   case Plot2d_Curve::Diamond:
479     ms = QwtSymbol::Diamond;   break;
480   case Plot2d_Curve::DTriangle:
481     ms = QwtSymbol::DTriangle; break;
482   case Plot2d_Curve::UTriangle:
483     ms = QwtSymbol::UTriangle; break;
484   case Plot2d_Curve::LTriangle: // Qwt confuses LTriangle and RTriangle :(((
485     ms = QwtSymbol::RTriangle; break;
486   case Plot2d_Curve::RTriangle: // Qwt confuses LTriangle and RTriangle :(((
487     ms = QwtSymbol::LTriangle; break;
488   case Plot2d_Curve::Cross:
489     ms = QwtSymbol::Cross;     break;
490   case Plot2d_Curve::XCross:
491     ms = QwtSymbol::XCross;    break;
492   case Plot2d_Curve::None:
493   default:
494     ms = QwtSymbol::None;      break;
495   }
496   return ms;
497 }
498
499 /*!
500   Converts Qwt marker style to Plot2d_Curve's marker style [ static ]
501 */
502 static Plot2d_Curve::MarkerType qwt2plotMarker( QwtSymbol::Style m )
503 {
504   Plot2d_Curve::MarkerType ms = Plot2d_Curve::None;  
505   switch ( m ) {
506   case QwtSymbol::Ellipse:
507     ms = Plot2d_Curve::Circle;    break;
508   case QwtSymbol::Rect:
509     ms = Plot2d_Curve::Rectangle; break;
510   case QwtSymbol::Diamond:
511     ms = Plot2d_Curve::Diamond;   break;
512   case QwtSymbol::DTriangle:
513     ms = Plot2d_Curve::DTriangle; break;
514   case QwtSymbol::UTriangle:
515     ms = Plot2d_Curve::UTriangle; break;
516   case QwtSymbol::RTriangle: // Qwt confuses LTriangle and RTriangle :(((
517     ms = Plot2d_Curve::LTriangle; break;
518   case QwtSymbol::LTriangle: // Qwt confuses LTriangle and RTriangle :(((
519     ms = Plot2d_Curve::RTriangle; break;
520   case QwtSymbol::Cross:
521     ms = Plot2d_Curve::Cross;     break;
522   case QwtSymbol::XCross:
523     ms = Plot2d_Curve::XCross;    break;
524   case QwtSymbol::None:
525   default:
526     ms = Plot2d_Curve::None;      break;
527   }
528   return ms;
529 }
530
531 /*!
532   Converts Plot2d_Curve's line style to Qwt line style [ static ]
533 */
534 static Qt::PenStyle plot2qwtLine( Plot2d_Curve::LineType p )
535 {
536   Qt::PenStyle ps = Qt::NoPen;
537   switch ( p ) {
538   case Plot2d_Curve::Solid:
539     ps = Qt::SolidLine;      break;
540   case Plot2d_Curve::Dash:
541     ps = Qt::DashLine;       break;
542   case Plot2d_Curve::Dot:
543     ps = Qt::DotLine;        break;
544   case Plot2d_Curve::DashDot:
545     ps = Qt::DashDotLine;    break;
546   case Plot2d_Curve::DashDotDot:
547     ps = Qt::DashDotDotLine; break;
548   case Plot2d_Curve::NoPen:
549   default:
550     ps = Qt::NoPen;          break;
551   }
552   return ps;
553 }
554
555 /*!
556   Converts Qwt line style to Plot2d_Curve's line style [ static ]
557 */
558 static Plot2d_Curve::LineType qwt2plotLine( Qt::PenStyle p )
559 {
560   Plot2d_Curve::LineType ps = Plot2d_Curve::NoPen;
561   switch ( p ) {
562   case Qt::SolidLine:
563     ps = Plot2d_Curve::Solid;      break;
564   case Qt::DashLine:
565     ps = Plot2d_Curve::Dash;       break;
566   case Qt::DotLine:
567     ps = Plot2d_Curve::Dot;        break;
568   case Qt::DashDotLine:
569     ps = Plot2d_Curve::DashDot;    break;
570   case Qt::DashDotDotLine:
571     ps = Plot2d_Curve::DashDotDot; break;
572   case Qt::NoPen:
573   default:
574     ps = Plot2d_Curve::NoPen;      break;
575   }
576   return ps;
577 }
578
579 /*!
580   Adds curve into view
581 */
582 void Plot2d_ViewFrame::displayCurve( Plot2d_Curve* curve, bool update )
583 {
584   if ( !curve )
585     return;
586   if ( hasCurve( curve ) ) {
587     updateCurve( curve, update );
588   }
589   else {
590     long curveKey = myPlot->insertCurve( curve->getVerTitle() );
591     myPlot->setCurveYAxis(curveKey, curve->getYAxis());
592
593     myCurves.insert( curveKey, curve );
594     if ( curve->isAutoAssign() ) {
595       QwtSymbol::Style typeMarker;
596       QColor           color;
597       Qt::PenStyle     typeLine;
598       myPlot->getNextMarker( typeMarker, color, typeLine );
599       myPlot->setCurvePen( curveKey, QPen( color, DEFAULT_LINE_WIDTH, typeLine ) );
600       myPlot->setCurveSymbol( curveKey, QwtSymbol( typeMarker, 
601                QBrush( color ), 
602                QPen( color ), 
603                QSize( myMarkerSize, myMarkerSize ) ) );
604       curve->setColor( color );
605       curve->setLine( qwt2plotLine( typeLine ) );
606       curve->setMarker( qwt2plotMarker( typeMarker ) );
607     }
608     else {
609       Qt::PenStyle     ps = plot2qwtLine( curve->getLine() );
610       QwtSymbol::Style ms = plot2qwtMarker( curve->getMarker() );
611       myPlot->setCurvePen( curveKey, QPen( curve->getColor(), curve->getLineWidth(), ps ) );
612       myPlot->setCurveSymbol( curveKey, QwtSymbol( ms, 
613                QBrush( curve->getColor() ), 
614                QPen( curve->getColor() ), 
615                QSize( myMarkerSize, myMarkerSize ) ) );
616     }
617     if ( myCurveType == 0 )
618       myPlot->setCurveStyle( curveKey, QwtCurve::NoCurve );
619     else if ( myCurveType == 1 )
620       myPlot->setCurveStyle( curveKey, QwtCurve::Lines );
621     else if ( myCurveType == 2 )
622       myPlot->setCurveStyle( curveKey, QwtCurve::Spline );
623     myPlot->setCurveData( curveKey, curve->horData(), curve->verData(), curve->nbPoints() );
624   }
625   if ( update )
626     myPlot->replot();
627 }
628
629 /*!
630   Adds curves into view
631 */
632 void Plot2d_ViewFrame::displayCurves( curveList curves, bool update )
633 {
634   myPlot->setUpdatesEnabled( false );
635   QPtrListIterator<Plot2d_Curve> it(curves);
636   Plot2d_Curve* aCurve;
637   while( (aCurve = it.current()) ) {
638     displayCurve( aCurve, false );
639     ++it;
640   }
641
642   fitAll();
643   myPlot->setUpdatesEnabled( true );
644   if ( update )
645     myPlot->replot();
646 }
647
648 /*!
649   Erases curve
650 */
651 void Plot2d_ViewFrame::eraseCurve( Plot2d_Curve* curve, bool update )
652 {
653   if ( !curve )
654     return;
655   int curveKey = hasCurve( curve );
656   if ( curveKey ) {
657     myPlot->removeCurve( curveKey );
658     myCurves.remove( curveKey );
659     if ( update )
660       myPlot->replot();
661   }
662 }
663
664 /*!
665   Erases curves
666 */
667 void Plot2d_ViewFrame::eraseCurves( curveList& curves, bool update )
668 {
669   QPtrListIterator<Plot2d_Curve> it(curves);
670   Plot2d_Curve* aCurve;
671   while( (aCurve = it.current()) ) {
672     eraseCurve( aCurve, false );
673     ++it;
674   }
675 //  fitAll();
676   if ( update )
677     myPlot->replot();
678 }
679
680 /*!
681   Updates curves attributes
682 */
683 void Plot2d_ViewFrame::updateCurve( Plot2d_Curve* curve, bool update )
684 {
685   if ( !curve )
686     return;
687   int curveKey = hasCurve( curve );
688   if ( curveKey ) {
689     if ( !curve->isAutoAssign() ) {
690       Qt::PenStyle     ps = plot2qwtLine( curve->getLine() );
691       QwtSymbol::Style ms = plot2qwtMarker( curve->getMarker() );
692       myPlot->setCurvePen( curveKey, QPen( curve->getColor(), curve->getLineWidth(), ps ) );
693       myPlot->setCurveSymbol( curveKey, QwtSymbol( ms, 
694                QBrush( curve->getColor() ), 
695                QPen( curve->getColor() ), 
696                QSize( myMarkerSize, myMarkerSize ) ) );
697       myPlot->setCurveData( curveKey, curve->horData(), curve->verData(), curve->nbPoints() );
698     }
699     myPlot->setCurveTitle( curveKey, curve->getVerTitle() );
700     myPlot->curve( curveKey )->setEnabled( true );
701     if ( update )
702       myPlot->replot();
703   }
704 }
705
706 /*!
707   Returns curve key if is is displayed in the viewer and 0 otherwise
708 */
709 int Plot2d_ViewFrame::hasCurve( Plot2d_Curve* curve )
710 {
711   QIntDictIterator<Plot2d_Curve> it( myCurves );
712   for ( ; it.current(); ++it ) {
713     if ( it.current() == curve )
714       return it.currentKey();
715   }
716   return 0;
717 }
718
719 /*!
720   Gets lsit of displayed curves
721 */
722 int Plot2d_ViewFrame::getCurves( QList<Plot2d_Curve>& clist )
723 {
724   clist.clear();
725   clist.setAutoDelete( false );
726   QIntDictIterator<Plot2d_Curve> it( myCurves );
727   for ( ; it.current(); ++it ) {
728     clist.append( it.current() );
729   }
730   return clist.count();
731 }
732
733 /*!
734   Returns true if the curve is visible
735 */
736 bool Plot2d_ViewFrame::isVisible( Plot2d_Curve* curve )
737 {
738   if(curve) {
739     int key = hasCurve( curve );
740     if ( key )
741       return myPlot->curve( key )->enabled();
742   }
743   return false;
744
745
746 /*!
747   update legend
748 */
749 void Plot2d_ViewFrame::updateLegend( const Plot2d_Prs* prs )
750 {
751   if ( !prs || prs->IsNull() )
752     return;
753   curveList aCurves = prs->getCurves();
754
755   QPtrListIterator<Plot2d_Curve> it(aCurves);
756   Plot2d_Curve* aCurve;
757   while( (aCurve = it.current()) ) {
758     int curveKey = hasCurve( aCurve );
759     if ( curveKey )
760       myPlot->setCurveTitle( curveKey, aCurve->getVerTitle() );
761     ++it;
762   }
763 }
764
765 /*!
766   Fits the view to see all data
767 */
768 void Plot2d_ViewFrame::fitAll()
769 {
770   QwtDiMap xMap1 = myPlot->canvasMap( QwtPlot::xBottom );
771
772   myPlot->setAxisAutoScale( QwtPlot::yLeft );
773   myPlot->setAxisAutoScale( QwtPlot::xBottom );
774   myPlot->replot();
775
776   // for existing grid
777   QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
778   QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
779
780   myPlot->setAxisScale( QwtPlot::xBottom, 
781       myPlot->invTransform( QwtPlot::xBottom, xMap.i1() ), 
782       myPlot->invTransform( QwtPlot::xBottom, xMap.i2() ) );
783   myPlot->setAxisScale( QwtPlot::yLeft, 
784       myPlot->invTransform( QwtPlot::yLeft, yMap.i1() ), 
785       myPlot->invTransform( QwtPlot::yLeft, yMap.i2() ) );
786
787   if (mySecondY) {
788     myPlot->setAxisAutoScale( QwtPlot::yRight );
789     myPlot->replot();
790     QwtDiMap yMap2 = myPlot->canvasMap( QwtPlot::yRight );
791     myPlot->setAxisScale( QwtPlot::yRight, 
792         myPlot->invTransform( QwtPlot::yRight, yMap2.i1() ), 
793         myPlot->invTransform( QwtPlot::yRight, yMap2.i2() ) );
794   }
795   myPlot->replot();
796 }
797
798 /*!
799   Fits the view to rectangle area (pixels)
800 */
801 void Plot2d_ViewFrame::fitArea( const QRect& area )
802 {
803   QRect rect = area.normalize();
804   if ( rect.width() < MIN_RECT_SIZE ) {
805     rect.setWidth( MIN_RECT_SIZE );
806     rect.setLeft( rect.left() - MIN_RECT_SIZE/2 );
807   }
808   if ( rect.height() < MIN_RECT_SIZE ) {
809     rect.setHeight( MIN_RECT_SIZE );
810     rect.setTop( rect.top() - MIN_RECT_SIZE/2 );
811   }
812   myPlot->setAxisScale( QwtPlot::yLeft, 
813             myPlot->invTransform( QwtPlot::yLeft, rect.top() ), 
814             myPlot->invTransform( QwtPlot::yLeft, rect.bottom() ) );
815   if (mySecondY)
816     myPlot->setAxisScale( QwtPlot::yRight, 
817             myPlot->invTransform( QwtPlot::yRight, rect.top() ), 
818             myPlot->invTransform( QwtPlot::yRight, rect.bottom() ) );
819   myPlot->setAxisScale( QwtPlot::xBottom, 
820             myPlot->invTransform( QwtPlot::xBottom, rect.left() ), 
821             myPlot->invTransform( QwtPlot::xBottom, rect.right() ) );
822   myPlot->replot();
823 }
824
825 /*!
826   Tests if it is necessary to start operation on mouse action
827 */
828 int Plot2d_ViewFrame::testOperation( const QMouseEvent& me )
829 {
830   int btn = me.button() | me.state();
831   const int zoomBtn = ControlButton | LeftButton;
832   const int panBtn  = ControlButton | MidButton;
833   const int fitBtn  = ControlButton | RightButton;
834
835   switch (btn)
836   {
837   case zoomBtn:
838     myPlot->canvas()->setCursor( zoomCursor );
839     return ZoomId;
840   case panBtn:
841     myPlot->canvas()->setCursor( QCursor( Qt::SizeAllCursor ) );
842     return PanId;
843   case fitBtn:
844     myPlot->canvas()->setCursor( QCursor( Qt::PointingHandCursor ) );
845     return FitAreaId;
846   default :
847     return NoOpId;
848   }
849 }
850
851 /*!
852   "Settings" toolbar action slot
853 */
854 void Plot2d_ViewFrame::onSettings()
855 {
856 #ifdef TEST_AUTOASSIGN
857   typedef QMap<int,int> IList;
858   typedef QMap<QString,int> SList;
859   IList mars, lins;
860   SList cols;
861   cols[ "red-min" ]   = 1000;
862   cols[ "red-max" ]   = -1;
863   cols[ "green-min" ] = 1000;
864   cols[ "green-max" ] = -1;
865   cols[ "blue-min" ]  = 1000;
866   cols[ "blue-max" ]  = -1;
867   for ( unsigned i = 0; i < 10000; i++ ) {
868     QwtSymbol::Style typeMarker;
869     QColor           color;
870     Qt::PenStyle     typeLine;
871     myPlot->getNextMarker( typeMarker, color, typeLine );
872     if ( mars.contains(typeMarker) )
873       mars[ typeMarker ] = mars[ typeMarker ]+1;
874     else
875       mars[ typeMarker ] = 0;
876     if ( lins.contains(typeLine) )
877       lins[ typeLine ] = lins[ typeLine ]+1;
878     else
879       lins[ typeLine ] = 0;
880     if ( cols[ "red-max" ] < color.red() )
881       cols[ "red-max" ] = color.red();
882     if ( cols[ "red-min" ] > color.red() )
883       cols[ "red-min" ] = color.red();
884     if ( cols[ "green-max" ] < color.green() )
885       cols[ "green-max" ] = color.green();
886     if ( cols[ "green-min" ] > color.green() )
887       cols[ "green-min" ] = color.green();
888     if ( cols[ "blue-max" ] < color.blue() )
889       cols[ "blue-max" ] = color.blue();
890     if ( cols[ "blue-min" ] > color.blue() )
891       cols[ "blue-min" ] = color.blue();
892   }
893   for (IList::Iterator it = mars.begin();  it != mars.end(); ++it)
894     MESSAGE("markers( " << it.key() << ") = " << it.data() );
895   for (IList::Iterator it = lins.begin();  it != lins.end(); ++it)
896     MESSAGE("lines( " << it.key() << ") = " << it.data() );
897   for (SList::Iterator it = cols.begin();  it != cols.end(); ++it)
898     MESSAGE("colors( " << it.key() << ") = " << it.data() );
899 #endif
900   
901   Plot2d_SetupViewDlg* dlg = new Plot2d_SetupViewDlg( this, true, mySecondY );
902   dlg->setMainTitle( myTitleEnabled, myTitle );
903   dlg->setXTitle( myXTitleEnabled, myXTitle );
904   dlg->setYTitle( myYTitleEnabled, myYTitle );
905   if (mySecondY)
906     dlg->setY2Title( myY2TitleEnabled, myY2Title );
907   dlg->setCurveType( myCurveType );
908   dlg->setLegend( myShowLegend, myLegendPos );
909   dlg->setMarkerSize( myMarkerSize );
910   dlg->setBackgroundColor( myBackground );
911   dlg->setScaleMode(myXMode, myYMode);
912   //
913   dlg->setMajorGrid( myXGridMajorEnabled, myPlot->axisMaxMajor( QwtPlot::xBottom ),
914          myYGridMajorEnabled, myPlot->axisMaxMajor( QwtPlot::yLeft ),
915          myY2GridMajorEnabled, myPlot->axisMaxMajor( QwtPlot::yRight ) );
916   dlg->setMinorGrid( myXGridMinorEnabled, myPlot->axisMaxMinor( QwtPlot::xBottom ),
917          myYGridMinorEnabled, myPlot->axisMaxMinor( QwtPlot::yLeft ),
918          myY2GridMinorEnabled, myPlot->axisMaxMinor( QwtPlot::yRight ) );
919   if ( dlg->exec() == QDialog::Accepted ) {
920     // horizontal axis title
921     setTitle( dlg->isXTitleEnabled(), dlg->getXTitle(), XTitle, false );
922     // vertical left axis title
923     setTitle( dlg->isYTitleEnabled(), dlg->getYTitle(), YTitle, false );
924     if (mySecondY) // vertical right axis title
925       setTitle( dlg->isY2TitleEnabled(), dlg->getY2Title(), Y2Title, false );
926
927     // main title
928     setTitle( dlg->isMainTitleEnabled(), dlg->getMainTitle(), MainTitle, true );
929     // curve type
930     if ( myCurveType != dlg->getCurveType() ) {
931       setCurveType( dlg->getCurveType(), false );
932     }
933     // legend
934     if ( myShowLegend != dlg->isLegendEnabled() ) {
935       showLegend( dlg->isLegendEnabled(), false );
936     }
937     if ( myLegendPos != dlg->getLegendPos() ) {
938       setLegendPos( dlg->getLegendPos() );
939     }
940     // marker size
941     if ( myMarkerSize != dlg->getMarkerSize() ) {
942       setMarkerSize( dlg->getMarkerSize(), false );
943     }
944     // background color
945     if ( myBackground != dlg->getBackgroundColor() ) {
946       setBackgroundColor( dlg->getBackgroundColor() );
947     }
948     // grid
949     bool aXGridMajorEnabled, aXGridMinorEnabled, aYGridMajorEnabled, aYGridMinorEnabled,
950          aY2GridMajorEnabled, aY2GridMinorEnabled;
951     int  aXGridMaxMajor, aXGridMaxMinor, aYGridMaxMajor, aYGridMaxMinor,
952          aY2GridMaxMajor, aY2GridMaxMinor;
953     dlg->getMajorGrid( aXGridMajorEnabled, aXGridMaxMajor, aYGridMajorEnabled, aYGridMaxMajor,
954                        aY2GridMajorEnabled, aY2GridMaxMajor);
955     dlg->getMinorGrid( aXGridMinorEnabled, aXGridMaxMinor, aYGridMinorEnabled, aYGridMaxMinor,
956                        aY2GridMinorEnabled, aY2GridMaxMinor);
957     setXGrid( aXGridMajorEnabled, aXGridMaxMajor, aXGridMinorEnabled, aXGridMaxMinor, false );
958     setYGrid( aYGridMajorEnabled, aYGridMaxMajor, aYGridMinorEnabled, aYGridMaxMinor,
959               aY2GridMajorEnabled, aY2GridMaxMajor, aY2GridMinorEnabled, aY2GridMaxMinor, false );
960     if ( myXMode != dlg->getXScaleMode() ) {
961       setHorScaleMode( dlg->getXScaleMode() );
962     }
963     if ( myYMode != dlg->getYScaleMode() ) {
964       setVerScaleMode( dlg->getYScaleMode() );
965     }
966     // update view
967     myPlot->replot();
968     // update preferences
969     if ( dlg->isSetAsDefault() ) 
970       writePreferences();
971   }
972   delete dlg;
973 }
974
975 /*!
976   "Fit Data" command slot
977 */
978 void Plot2d_ViewFrame::onFitData()
979 {
980   Plot2d_FitDataDlg* dlg = new Plot2d_FitDataDlg( this, mySecondY );
981   int ixMin = myPlot->canvasMap( QwtPlot::xBottom ).i1();
982   int ixMax = myPlot->canvasMap( QwtPlot::xBottom ).i2();
983   int iyMin = myPlot->canvasMap( QwtPlot::yLeft ).i1();
984   int iyMax = myPlot->canvasMap( QwtPlot::yLeft ).i2();
985   double xMin = myPlot->invTransform(QwtPlot::xBottom, ixMin);
986   double xMax = myPlot->invTransform(QwtPlot::xBottom, ixMax);
987   double yMin = myPlot->invTransform(QwtPlot::yLeft, iyMin);
988   double yMax = myPlot->invTransform(QwtPlot::yLeft, iyMax);
989   double y2Min = 0;
990   double y2Max = 0;
991   if (mySecondY) {
992     int iyMin = myPlot->canvasMap( QwtPlot::yRight ).i1();
993     int iyMax = myPlot->canvasMap( QwtPlot::yRight ).i2();
994     y2Min = myPlot->invTransform(QwtPlot::yRight, iyMin);
995     y2Max = myPlot->invTransform(QwtPlot::yRight, iyMax);
996   }
997   
998   dlg->setRange( xMin, xMax, yMin, yMax, y2Min, y2Max );
999   if ( dlg->exec() == QDialog::Accepted ) {
1000     int mode = dlg->getRange( xMin, xMax, yMin, yMax, y2Min, y2Max );
1001     if ( mode == 0 || mode == 2 ) {
1002       myPlot->setAxisScale( QwtPlot::yLeft, yMax, yMin );
1003       if (mySecondY)
1004         myPlot->setAxisScale( QwtPlot::yRight, y2Max, y2Min );
1005     }
1006     if ( mode == 0 || mode == 1 ) 
1007       myPlot->setAxisScale( QwtPlot::xBottom, xMin, xMax ); 
1008     myPlot->replot();
1009   }
1010   delete dlg;
1011 }
1012
1013 /*!
1014   Change background color
1015 */
1016 void Plot2d_ViewFrame::onChangeBackground()
1017 {
1018   QColor selColor = QColorDialog::getColor ( backgroundColor(), this ); 
1019   if ( selColor.isValid() ) {
1020     setBackgroundColor( selColor );
1021   }
1022 }
1023
1024 /*!
1025   Sets curve type
1026 */
1027 void Plot2d_ViewFrame::setCurveType( int curveType, bool update )
1028 {
1029   myCurveType = curveType;
1030   QArray<long> keys = myPlot->curveKeys();
1031   for ( int i = 0; i < (int)keys.count(); i++ ) {
1032     if ( myCurveType == 0 )
1033       myPlot->setCurveStyle( keys[i], QwtCurve::Dots );//QwtCurve::NoCurve
1034     else if ( myCurveType == 1 )
1035       myPlot->setCurveStyle( keys[i], QwtCurve::Lines );
1036     else if ( myCurveType == 2 )
1037       myPlot->setCurveStyle( keys[i], QwtCurve::Spline );
1038   }
1039   if ( update )
1040     myPlot->replot();
1041   emit vpCurveChanged();
1042 }
1043
1044 void Plot2d_ViewFrame::setCurveTitle( int curveKey, const QString& title ) 
1045
1046   if(myPlot) myPlot->setCurveTitle(curveKey, title); 
1047 }   
1048
1049 /*!
1050   Shows/hides legend
1051 */
1052 void Plot2d_ViewFrame::showLegend( bool show, bool update )
1053 {
1054   myShowLegend = show;
1055   myPlot->setAutoLegend( myShowLegend );
1056   myPlot->enableLegend( myShowLegend );
1057   if ( update )
1058     myPlot->replot();
1059 }
1060
1061 /*!
1062   Sets legend position : 0 - left, 1 - right, 2 - top, 3 - bottom
1063 */
1064 void Plot2d_ViewFrame::setLegendPos( int pos )
1065 {
1066   myLegendPos = pos;
1067   switch( pos ) {
1068   case 0:
1069     myPlot->setLegendPos( Qwt::Left );
1070     break;
1071   case 1:
1072     myPlot->setLegendPos( Qwt::Right );
1073     break;
1074   case 2:
1075     myPlot->setLegendPos( Qwt::Top );
1076     break;
1077   case 3:
1078     myPlot->setLegendPos( Qwt::Bottom );
1079     break;
1080   }
1081 }
1082
1083 /*!
1084   Sets new marker size
1085 */
1086 void Plot2d_ViewFrame::setMarkerSize( const int size, bool update )
1087 {
1088   if ( myMarkerSize != size )
1089   {
1090     myMarkerSize = size;
1091     QArray<long> keys = myPlot->curveKeys();
1092     for ( int i = 0; i < (int)keys.count(); i++ )
1093     {
1094       QwtPlotCurve* crv = myPlot->curve( keys[i] );
1095       if ( crv )
1096       {
1097         QwtSymbol aSymbol = crv->symbol();
1098         aSymbol.setSize( myMarkerSize, myMarkerSize );
1099         myPlot->setCurveSymbol( keys[i], aSymbol );
1100       }
1101     }
1102     if ( update )
1103       myPlot->replot();
1104   }
1105 }
1106
1107 /*!
1108   Sets background color
1109 */
1110 void Plot2d_ViewFrame::setBackgroundColor( const QColor& color )
1111 {
1112   myBackground = color;
1113   //myPlot->setCanvasBackground( myBackground );
1114   myPlot->canvas()->setPalette( myBackground );
1115   myPlot->setPalette( myBackground );
1116   QPalette aPal = myPlot->getLegend()->palette();
1117   for ( int i = 0; i < QPalette::NColorGroups; i++ ) {
1118     QPalette::ColorGroup cg = (QPalette::ColorGroup)i;
1119     aPal.setColor( cg, QColorGroup::Base, myBackground );
1120     aPal.setColor( cg, QColorGroup::Background, myBackground );
1121   }
1122   myPlot->getLegend()->setPalette( aPal );
1123   Repaint();
1124 }
1125 /*!
1126   Gets background color
1127 */
1128 QColor Plot2d_ViewFrame::backgroundColor() const
1129 {
1130   return myBackground;
1131 }
1132 /*!
1133   Sets hor.axis grid parameters
1134 */
1135 void Plot2d_ViewFrame::setXGrid( bool xMajorEnabled, const int xMajorMax, 
1136          bool xMinorEnabled, const int xMinorMax, 
1137          bool update )
1138 {
1139   myXGridMajorEnabled = xMajorEnabled;
1140   myXGridMinorEnabled = xMinorEnabled;
1141   myXGridMaxMajor = xMajorMax;
1142   myXGridMaxMinor = xMinorMax;
1143   myPlot->setAxisMaxMajor( QwtPlot::xBottom, myXGridMaxMajor );
1144   myPlot->setAxisMaxMinor( QwtPlot::xBottom, myXGridMaxMinor );
1145   myPlot->setGridXAxis(QwtPlot::xBottom);
1146   myPlot->enableGridX( myXGridMajorEnabled );
1147   myPlot->enableGridXMin( myXGridMinorEnabled );
1148   if ( update )
1149     myPlot->replot();
1150 }
1151 /*!
1152   Sets ver.axis grid parameters
1153 */
1154 void Plot2d_ViewFrame::setYGrid( bool yMajorEnabled, const int yMajorMax, 
1155                                  bool yMinorEnabled, const int yMinorMax,
1156                                  bool y2MajorEnabled, const int y2MajorMax, 
1157                                  bool y2MinorEnabled, const int y2MinorMax, 
1158                                  bool update )
1159 {
1160   myYGridMajorEnabled = yMajorEnabled;
1161   myYGridMinorEnabled = yMinorEnabled;
1162   myYGridMaxMajor = yMajorMax;
1163   myYGridMaxMinor = yMinorMax;
1164
1165   if (mySecondY) {
1166     myY2GridMajorEnabled = y2MajorEnabled;
1167     myY2GridMinorEnabled = y2MinorEnabled;
1168     myY2GridMaxMajor = y2MajorMax;
1169     myY2GridMaxMinor = y2MinorMax;
1170   }
1171   myPlot->setAxisMaxMajor( QwtPlot::yLeft, myYGridMaxMajor );
1172   myPlot->setAxisMaxMinor( QwtPlot::yLeft, myYGridMaxMinor );
1173
1174   if (mySecondY) {
1175     myPlot->setAxisMaxMajor( QwtPlot::yRight, myY2GridMaxMajor );
1176     myPlot->setAxisMaxMinor( QwtPlot::yRight, myY2GridMaxMinor );
1177   }
1178
1179   myPlot->setGridYAxis(QwtPlot::yLeft);
1180
1181   if (mySecondY) {
1182     if (myYGridMajorEnabled) {
1183       myPlot->enableGridYMin(myYGridMinorEnabled);
1184       myPlot->enableGridY( myYGridMajorEnabled);
1185     }
1186     else if (myY2GridMajorEnabled) {
1187       myPlot->setGridYAxis(QwtPlot::yRight);
1188       myPlot->enableGridYMin(myY2GridMinorEnabled);
1189       myPlot->enableGridY(myY2GridMajorEnabled);
1190     }
1191     else {
1192       myPlot->enableGridYMin(false);
1193       myPlot->enableGridY(false);
1194     }
1195   }
1196   else {
1197     myPlot->enableGridY( myYGridMajorEnabled );
1198     myPlot->enableGridYMin( myYGridMinorEnabled );
1199   }
1200   if ( update )
1201     myPlot->replot();
1202 }
1203
1204 /*!
1205   Sets title for some axis
1206 */
1207 void Plot2d_ViewFrame::setTitle( bool enabled, const QString& title,
1208                                  ObjectType type, bool update )
1209 {
1210   switch (type) {
1211     case MainTitle:
1212       myTitleEnabled = enabled;
1213       myTitle = title;
1214       myPlot->setTitle( myTitleEnabled ? myTitle : QString::null );
1215       break;
1216     case XTitle:
1217       myXTitleEnabled = enabled;
1218       myXTitle = title;
1219       myPlot->setAxisTitle( QwtPlot::xBottom, myXTitleEnabled ? myXTitle : QString::null );
1220       break;
1221     case YTitle:
1222       myYTitleEnabled = enabled;
1223       myYTitle = title;
1224       myPlot->setAxisTitle( QwtPlot::yLeft, myYTitleEnabled ? myYTitle : QString::null );
1225       break;
1226     case Y2Title:
1227       myY2TitleEnabled = enabled;
1228       myY2Title = title;
1229       myPlot->setAxisTitle( QwtPlot::yRight, myY2TitleEnabled ? myY2Title : QString::null );
1230       break;
1231   }
1232   if ( update )
1233     myPlot->replot();
1234 }
1235 /*!
1236   Sets title for some axis
1237 */
1238 QString Plot2d_ViewFrame::getTitle( ObjectType type ) const
1239 {
1240   QString title = "";
1241   switch (type) {
1242     case MainTitle:
1243       title = myTitle;   break;
1244     case XTitle:
1245       title = myXTitle;  break;
1246     case YTitle:
1247       title = myYTitle;  break;
1248     case Y2Title:
1249       title = myY2Title; break;
1250   }
1251   return title;
1252 }
1253 /*!
1254   Sets font for Plot2d object : title or axis
1255 */
1256 void Plot2d_ViewFrame::setFont( const QFont& font, ObjectType type, bool update)
1257 {
1258   switch (type) {
1259     case MainTitle:
1260       myPlot->setTitleFont(font);
1261       break;
1262     case XTitle:
1263       myPlot->setAxisTitleFont(QwtPlot::xBottom, font); break;
1264     case YTitle:
1265       myPlot->setAxisTitleFont(QwtPlot::yLeft, font);   break;
1266     case Y2Title:
1267       myPlot->setAxisTitleFont(QwtPlot::yRight, font);  break;
1268     case XAxis:
1269       myPlot->setAxisFont(QwtPlot::xBottom, font);      break;
1270     case YAxis:
1271       myPlot->setAxisFont(QwtPlot::yLeft, font);        break;
1272     case Y2Axis:
1273       myPlot->setAxisFont(QwtPlot::yRight, font);       break;
1274   }
1275   if ( update )
1276     myPlot->replot();
1277 }
1278 /*!
1279   Sets scale mode for horizontal axis: 0 - linear, 1 - logarithmic
1280 */
1281 void Plot2d_ViewFrame::setHorScaleMode( const int mode, bool update )
1282 {
1283   myXMode = mode;
1284   if ( myXMode == 0 ) // linear
1285     myPlot->changeAxisOptions( QwtPlot::xBottom, QwtAutoScale::Logarithmic, false );
1286   else                // logarithmic
1287     myPlot->changeAxisOptions( QwtPlot::xBottom, QwtAutoScale::Logarithmic, true );
1288
1289   if ( update )
1290     fitAll();
1291   emit vpModeHorChanged();
1292 }
1293 /*!
1294   Sets scale mode for vertical axis: 0 - linear, 1 - logarithmic
1295 */
1296 void Plot2d_ViewFrame::setVerScaleMode( const int mode, bool update )
1297 {
1298   myYMode = mode;
1299   if ( myYMode == 0 ) { // linear
1300     myPlot->changeAxisOptions( QwtPlot::yLeft, QwtAutoScale::Logarithmic, false );
1301     if (mySecondY)
1302       myPlot->changeAxisOptions( QwtPlot::yRight, QwtAutoScale::Logarithmic, false );
1303   }
1304   else {               // logarithmic
1305     myPlot->changeAxisOptions( QwtPlot::yLeft, QwtAutoScale::Logarithmic, true );
1306     if (mySecondY)
1307       myPlot->changeAxisOptions( QwtPlot::yRight, QwtAutoScale::Logarithmic, true );
1308   }
1309   if ( update )
1310     fitAll();
1311   emit vpModeVerChanged();
1312 }
1313
1314 /*!
1315   Return, scale mode for horizontal axis
1316 */
1317 bool Plot2d_ViewFrame::isModeHorLinear()
1318 {
1319   return (myXMode == 0 ? true : false);
1320 }
1321
1322 /*!
1323   Return, scale mode for vertical axis
1324 */
1325 bool Plot2d_ViewFrame::isModeVerLinear()
1326 {
1327   return (myYMode == 0 ? true : false);
1328 }
1329 /*!
1330   Slot, called when user presses mouse button
1331 */
1332 void Plot2d_ViewFrame::plotMousePressed(const QMouseEvent& me )
1333 {
1334   if ( myOperation == NoOpId )
1335     myOperation = testOperation( me );
1336   if ( myOperation != NoOpId ) {
1337     myPnt = me.pos();
1338     if ( myOperation == FitAreaId ) {
1339       myPlot->setOutlineStyle( Qwt::Rect );
1340     }
1341     else if ( myOperation == GlPanId ) {
1342       myPlot->setAxisScale( QwtPlot::yLeft,
1343           myPlot->invTransform( QwtPlot::yLeft, myPnt.y() ) + myYDistance/2, 
1344           myPlot->invTransform( QwtPlot::yLeft, myPnt.y() ) - myYDistance/2 );
1345       myPlot->setAxisScale( QwtPlot::xBottom, 
1346           myPlot->invTransform( QwtPlot::xBottom, myPnt.x() ) - myXDistance/2, 
1347           myPlot->invTransform( QwtPlot::xBottom, myPnt.x() ) + myXDistance/2 );
1348       if (mySecondY)
1349         myPlot->setAxisScale( QwtPlot::yRight,
1350           myPlot->invTransform( QwtPlot::yRight, myPnt.y() ) + myYDistance2/2, 
1351           myPlot->invTransform( QwtPlot::yRight, myPnt.y() ) - myYDistance2/2 );
1352       myPlot->replot();
1353     }
1354   }
1355   else {
1356     int btn = me.button() | me.state();
1357     if (btn == RightButton) {
1358       QMouseEvent* aEvent = new QMouseEvent(QEvent::MouseButtonPress,
1359                                             me.pos(), btn, me.state());
1360       // QMouseEvent 'me' has the 'MouseButtonDblClick' type. In this case we create new event 'aEvent'.
1361       parent()->eventFilter(this, aEvent);
1362     }
1363   }
1364 }
1365 /*!
1366   Slot, called when user moves mouse
1367 */
1368 void Plot2d_ViewFrame::plotMouseMoved( const QMouseEvent& me )
1369 {
1370   int    dx = me.pos().x() - myPnt.x();
1371   int    dy = me.pos().y() - myPnt.y();
1372
1373   if ( myOperation != NoOpId) {
1374     if ( myOperation == ZoomId ) {
1375       QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
1376       QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
1377
1378       myPlot->setAxisScale( QwtPlot::yLeft, 
1379           myPlot->invTransform( QwtPlot::yLeft, yMap.i1() ), 
1380           myPlot->invTransform( QwtPlot::yLeft, yMap.i2() + dy ) );
1381       myPlot->setAxisScale( QwtPlot::xBottom, 
1382           myPlot->invTransform( QwtPlot::xBottom, xMap.i1() ), 
1383           myPlot->invTransform( QwtPlot::xBottom, xMap.i2() - dx ) );
1384       if (mySecondY) {
1385         QwtDiMap y2Map = myPlot->canvasMap( QwtPlot::yRight );
1386         myPlot->setAxisScale( QwtPlot::yRight, 
1387           myPlot->invTransform( QwtPlot::yRight, y2Map.i1() ), 
1388           myPlot->invTransform( QwtPlot::yRight, y2Map.i2() + dy ) );
1389       }
1390       myPlot->replot();
1391       myPnt = me.pos();
1392     }
1393     else if ( myOperation == PanId ) {
1394       QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
1395       QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
1396
1397       myPlot->setAxisScale( QwtPlot::yLeft, 
1398           myPlot->invTransform( QwtPlot::yLeft, yMap.i1()-dy ), 
1399           myPlot->invTransform( QwtPlot::yLeft, yMap.i2()-dy ) );
1400       myPlot->setAxisScale( QwtPlot::xBottom, 
1401           myPlot->invTransform( QwtPlot::xBottom, xMap.i1()-dx ),
1402           myPlot->invTransform( QwtPlot::xBottom, xMap.i2()-dx ) ); 
1403       if (mySecondY) {
1404         QwtDiMap y2Map = myPlot->canvasMap( QwtPlot::yRight );
1405         myPlot->setAxisScale( QwtPlot::yRight,
1406           myPlot->invTransform( QwtPlot::yRight, y2Map.i1()-dy ), 
1407           myPlot->invTransform( QwtPlot::yRight, y2Map.i2()-dy ) );
1408       }
1409       myPlot->replot();
1410       myPnt = me.pos();
1411     }
1412   }
1413   else {
1414     ((Plot2d_ViewWindow*)parent())->putInfo(getInfo(me.pos()));
1415   }
1416 }
1417 /*!
1418   Slot, called when user releases mouse
1419 */
1420 void Plot2d_ViewFrame::plotMouseReleased( const QMouseEvent& me )
1421 {
1422   if ( myOperation == NoOpId && me.button() == RightButton )
1423   {
1424     QContextMenuEvent aEvent( QContextMenuEvent::Mouse,
1425                               me.pos(), me.globalPos(),
1426                               me.state() );
1427     emit contextMenuRequested( &aEvent );
1428   }
1429   if ( myOperation == FitAreaId ) {
1430     QRect rect( myPnt, me.pos() );
1431     fitArea( rect );
1432   }
1433   myPlot->canvas()->setCursor( QCursor( Qt::CrossCursor ) );
1434   myPlot->setOutlineStyle( Qwt::Triangle );
1435
1436   ((Plot2d_ViewWindow*)parent())->putInfo(tr("INF_READY"));
1437   myOperation = NoOpId;
1438 }
1439 /*!
1440   Slot, called when user wheeling mouse
1441 */
1442 void Plot2d_ViewFrame::wheelEvent(QWheelEvent* event)
1443
1444   double aDelta = event->delta();
1445   double aScale = (aDelta < 0) ? 100./(-aDelta) : aDelta/100.; 
1446
1447   QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
1448   QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
1449
1450   myPlot->setAxisScale( QwtPlot::yLeft,
1451     myPlot->invTransform( QwtPlot::yLeft, yMap.i1() ), 
1452     myPlot->invTransform( QwtPlot::yLeft, yMap.i2() )*aScale );
1453   myPlot->setAxisScale( QwtPlot::xBottom, 
1454     myPlot->invTransform( QwtPlot::xBottom, xMap.i1() ),
1455     myPlot->invTransform( QwtPlot::xBottom, xMap.i2() )*aScale );
1456   if (mySecondY) {
1457     QwtDiMap y2Map = myPlot->canvasMap( QwtPlot::yRight );
1458     myPlot->setAxisScale( QwtPlot::yRight,
1459       myPlot->invTransform( QwtPlot::yRight, y2Map.i1() ), 
1460       myPlot->invTransform( QwtPlot::yRight, y2Map.i2() )*aScale );
1461   }
1462   myPlot->replot();
1463   myPnt = event->pos();
1464 }
1465 /*!
1466   View operations : Pan view
1467 */
1468 void Plot2d_ViewFrame::onViewPan()
1469
1470   myPlot->canvas()->setCursor( panCursor );
1471   myOperation = PanId;
1472   qApp->installEventFilter( this );
1473 }
1474 /*!
1475   View operations : Zoom view
1476 */
1477 void Plot2d_ViewFrame::onViewZoom() 
1478 {
1479   myPlot->canvas()->setCursor( zoomCursor );
1480   myOperation = ZoomId;
1481   qApp->installEventFilter( this );
1482 }
1483 /*!
1484   View operations : Fot All
1485 */
1486 void Plot2d_ViewFrame::onViewFitAll() 
1487
1488   fitAll();
1489 }
1490 /*!
1491   View operations : Fit Area
1492 */
1493 void Plot2d_ViewFrame::onViewFitArea() 
1494 {
1495   myPlot->canvas()->setCursor( QCursor( Qt::PointingHandCursor ) );
1496   myOperation = FitAreaId;
1497   qApp->installEventFilter( this );
1498 }
1499 /*!
1500   View operations : Global panning
1501 */
1502 void Plot2d_ViewFrame::onViewGlobalPan() 
1503 {
1504   myPlot->canvas()->setCursor( glPanCursor );
1505   myPlot->changeAxisOptions( QwtPlot::xBottom, QwtAutoScale::Logarithmic, false );
1506   myPlot->changeAxisOptions( QwtPlot::yLeft, QwtAutoScale::Logarithmic, false );
1507   if (mySecondY)
1508     myPlot->changeAxisOptions( QwtPlot::yRight, QwtAutoScale::Logarithmic, false );
1509   myPlot->replot();
1510   QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
1511   QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
1512
1513   myXDistance = xMap.d2() - xMap.d1();
1514   myYDistance = yMap.d2() - yMap.d1();
1515
1516   if (mySecondY) {
1517     QwtDiMap yMap2 = myPlot->canvasMap( QwtPlot::yRight );
1518     myYDistance2 = yMap2.d2() - yMap2.d1();
1519   }
1520   fitAll();
1521   myOperation = GlPanId;
1522   qApp->installEventFilter( this );
1523 }
1524
1525 //=================================================================================
1526 // Plot2d_Plot2d implementation
1527 //=================================================================================
1528 /*!
1529   Constructor
1530 */
1531 Plot2d_Plot2d::Plot2d_Plot2d( QWidget* parent )
1532      : QwtPlot( parent )
1533 {
1534   // outline
1535   enableOutline( true );
1536   setOutlineStyle( Qwt::Triangle );
1537   setOutlinePen( green );
1538   // legend
1539   setAutoLegend( false );
1540   setLegendFrameStyle( QFrame::Box | QFrame::Sunken );
1541   enableLegend( false );
1542   // grid
1543   enableGridX( false );
1544   enableGridXMin( false );
1545   enableGridY( false );
1546   enableGridYMin( false );
1547   // auto scaling by default
1548   setAxisAutoScale( QwtPlot::yLeft );
1549   setAxisAutoScale( QwtPlot::yRight );
1550   setAxisAutoScale( QwtPlot::xBottom );
1551 }
1552 /*!
1553   Recalculates and redraws Plot 2d view 
1554 */
1555 void Plot2d_Plot2d::replot()
1556 {
1557   updateLayout();  // to fix bug(?) of Qwt - view is not updated when title is changed
1558   QwtPlot::replot(); 
1559 }
1560
1561 /*!
1562   Checks if two colors are close to each other [ static ]
1563   uses COLOR_DISTANCE variable as max tolerance for comparing of colors
1564 */
1565 const long COLOR_DISTANCE = 100;
1566 const int  MAX_ATTEMPTS   = 10;
1567 static bool closeColors( const QColor& color1, const QColor& color2 )
1568 {
1569   long tol = abs( color2.red()   - color1.red() ) + 
1570              abs( color2.green() - color1.green() ) +
1571        abs( color2.blue()  - color1.blue() );
1572
1573   return ( tol <= COLOR_DISTANCE );
1574 }
1575 /*!
1576   Gets new unique marker for item if possible
1577 */
1578 void Plot2d_Plot2d::getNextMarker( QwtSymbol::Style& typeMarker, QColor& color, Qt::PenStyle& typeLine ) 
1579 {
1580   bool bOk = false;
1581   int cnt = 1;
1582   while ( !bOk ) {
1583     int aRed    = (int)( 256.0 * rand() / RAND_MAX);    // generate random color
1584     int aGreen  = (int)( 256.0 * rand() / RAND_MAX);    // ...
1585     int aBlue   = (int)( 256.0 * rand() / RAND_MAX);    // ...
1586     int aMarker = (int)( 9.0 * rand() / RAND_MAX) + 1;  // 9 markers types ( not including empty )
1587     int aLine   = (int)( 5.0 * rand() / RAND_MAX) + 1;  // 5 line types ( not including empty )
1588
1589     typeMarker = ( QwtSymbol::Style )aMarker;
1590     color      = QColor( aRed, aGreen, aBlue );
1591     typeLine   = ( Qt::PenStyle )aLine;
1592
1593     cnt++;
1594     if ( cnt == MAX_ATTEMPTS )
1595       bOk = true;
1596     else
1597       bOk = !existMarker( typeMarker, color, typeLine );
1598   }
1599 /*
1600   static int aMarker = -1;
1601   static int aColor  = -1;
1602   static int aLine   = -1;
1603
1604   if ( myColors.isEmpty() ) {
1605     // creating colors list
1606     myColors.append( Qt::white );
1607     myColors.append( Qt::blue );
1608     myColors.append( Qt::gray );
1609     myColors.append( Qt::darkGreen );
1610     myColors.append( Qt::magenta );
1611     myColors.append( Qt::darkGray );
1612     myColors.append( Qt::red );
1613     myColors.append( Qt::darkBlue );
1614     myColors.append( Qt::darkYellow );
1615     myColors.append( Qt::cyan );
1616     myColors.append( Qt::darkRed );
1617     myColors.append( Qt::darkCyan );
1618     myColors.append( Qt::yellow );
1619     myColors.append( Qt::darkMagenta );
1620     myColors.append( Qt::green );
1621     myColors.append( Qt::black );
1622   }
1623
1624   int nbMarkers = 11;                   // QwtSymbol supports 11 marker types
1625   int nbLines   = 6;                    // Qt supports 6 line types
1626   int nbColors  = myColors.count();     // number of default colors supported
1627
1628   aMarker = ( aMarker + 1 ) % nbMarkers;  
1629   if ( aMarker == QwtSymbol::None || aMarker == QwtSymbol::Triangle ) aMarker++;
1630   aColor  = ( aColor  + 1 ) % nbColors;
1631   aLine   = ( aLine   + 1 ) % nbLines;    
1632   if ( aLine == Qt::NoPen ) aLine++;             
1633
1634   typeMarker = ( QwtSymbol::Style )aMarker;
1635   color      = myColors[ aColor ];
1636   typeLine   = ( Qt::PenStyle )aLine;
1637   if ( !existMarker( typeMarker, color, typeLine ) )
1638     return;
1639
1640   int i, j, k;
1641   for ( i = 0; i < nbMarkers; i++ ) {
1642     aMarker = ( aMarker + 1 ) % nbMarkers;
1643     if ( aMarker == QwtSymbol::None || aMarker == QwtSymbol::Triangle ) aMarker++;
1644     for ( j = 0; j < nbColors; j++ ) {
1645       aColor  = ( aColor  + 1 ) % nbColors;
1646       for ( k = 0; k < nbLines; k++ ) {
1647         aLine = ( aLine + 1 ) % nbLines;
1648   if ( aLine == Qt::NoPen ) aLine++;             
1649         if ( !existMarker( ( QwtSymbol::Style )aMarker, aColor, ( Qt::PenStyle )aLine ) ) {
1650           typeMarker = ( QwtSymbol::Style )aMarker;
1651           color      = myColors[ aColor ];
1652           typeLine   = ( Qt::PenStyle )aLine;
1653           return;
1654         }
1655       }
1656     }
1657   }
1658 */
1659 }
1660
1661 QSizePolicy Plot2d_Plot2d::sizePolicy() const
1662 {
1663   return QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
1664 }
1665
1666 QSize Plot2d_Plot2d::sizeHint() const
1667 {
1668   return QwtPlot::minimumSizeHint();
1669 }
1670
1671 /*!
1672   return minimum size for qwt plot
1673 */
1674 QSize Plot2d_Plot2d::minimumSizeHint() const
1675 {
1676   return QSize( 0, 0 );
1677 //  QSize aSize = QwtPlot::minimumSizeHint();
1678 //  return QSize(aSize.width()*3/4, aSize.height());
1679 }
1680 /*!
1681   Checks if marker belongs to any enitity
1682 */
1683 bool Plot2d_Plot2d::existMarker( const QwtSymbol::Style typeMarker, const QColor& color, const Qt::PenStyle typeLine ) 
1684 {
1685   // getting all curves
1686   QArray<long> keys = curveKeys();
1687   //QColor aRgbColor;
1688
1689   if ( closeColors( color, backgroundColor() ) )
1690       return true;
1691   for ( int i = 0; i < (int)keys.count(); i++ )
1692   {
1693     QwtPlotCurve* crv = curve( keys[i] );
1694     if ( crv ) {
1695       QwtSymbol::Style aStyle = crv->symbol().style();
1696       QColor           aColor = crv->pen().color();
1697       Qt::PenStyle     aLine  = crv->pen().style();
1698 //      if ( aStyle == typeMarker && aColor == color && aLine == typeLine )
1699       if ( aStyle == typeMarker && closeColors( aColor,color ) && aLine == typeLine )
1700   return true;
1701     }
1702   }
1703   return false;
1704 }