Salome HOME
Moved some functionality to VTKViewer_Utilities.h
[modules/kernel.git] / src / Plot2d / Plot2d_ViewFrame.cxx
1 //  Copyright (C) 2003  CEA/DEN, EDF R&D
2 //
3 //
4 //
5 //  File   : Plot2d_ViewFrame.cxx
6 //  Author : Vadim SANDLER
7 //  Module : SALOME
8 //  $Header$
9
10 #include "Plot2d_ViewFrame.h"
11 #include "Plot2d_SetupViewDlg.h"
12 #include "Plot2d_Prs.h"
13
14 #include "QAD_Desktop.h"
15 #include "QAD_ResourceMgr.h"
16 #include "QAD_FileDlg.h"
17 #include "QAD_Tools.h"
18 #include "QAD_MessageBox.h"
19 #include "QAD_Config.h"
20 #include "SALOME_Selection.h"
21 #include "Plot2d_CurveContainer.h"
22 #include "Plot2d_Curve.h"
23 #include "Plot2d_FitDataDlg.h"
24 #include "utilities.h"
25 #include "qapplication.h"
26 #include <qtoolbar.h>
27 #include <qtoolbutton.h>
28 #include <qcursor.h>
29 #include <qcolordialog.h>
30 #include <qwt_math.h>
31 #include <qwt_plot_canvas.h>
32 #include <stdlib.h>
33 #include "utilities.h"
34
35 // IDL headers
36 #include <SALOMEconfig.h>
37 #include CORBA_SERVER_HEADER(SALOMEDS)
38 #include CORBA_SERVER_HEADER(SALOMEDS_Attributes)
39 using namespace std;
40
41 #define DEFAULT_LINE_WIDTH     0     // (default) line width
42 #define DEFAULT_MARKER_SIZE    9     // default marker size
43 #define MIN_RECT_SIZE          11    // min sensibility area size
44
45 /* XPM */
46 const char* imageZoomCursor[] = { 
47 "32 32 3 1",
48 ". c None",
49 "a c #000000",
50 "# c #ffffff",
51 "................................",
52 "................................",
53 ".#######........................",
54 "..aaaaaaa.......................",
55 "................................",
56 ".............#####..............",
57 "...........##.aaaa##............",
58 "..........#.aa.....a#...........",
59 ".........#.a.........#..........",
60 ".........#a..........#a.........",
61 "........#.a...........#.........",
62 "........#a............#a........",
63 "........#a............#a........",
64 "........#a............#a........",
65 "........#a............#a........",
66 ".........#...........#.a........",
67 ".........#a..........#a.........",
68 ".........##.........#.a.........",
69 "........#####.....##.a..........",
70 ".......###aaa#####.aa...........",
71 "......###aa...aaaaa.......#.....",
72 ".....###aa................#a....",
73 "....###aa.................#a....",
74 "...###aa...............#######..",
75 "....#aa.................aa#aaaa.",
76 ".....a....................#a....",
77 "..........................#a....",
78 "...........................a....",
79 "................................",
80 "................................",
81 "................................",
82 "................................"};
83
84
85 //=================================================================================
86 // Plot2d_ViewFrame implementation
87 //=================================================================================
88
89 /*!
90   Constructor
91 */
92 Plot2d_ViewFrame::Plot2d_ViewFrame( QWidget* parent, const QString& title )
93      : QAD_ViewFrame( parent, title ),
94        myOperation( NoOpId ), 
95        myCurveType( 1 ), 
96        myShowLegend( true ), myLegendPos( 1 ),
97        myMarkerSize( DEFAULT_MARKER_SIZE ),
98        myTitle( "" ), myXTitle( "" ), myYTitle( "" ),
99        myBackground( white ),
100        myTitleEnabled( true ), myXTitleEnabled( true ), myYTitleEnabled( true ),
101        myXGridMajorEnabled( true ), myYGridMajorEnabled( true ), 
102        myXGridMinorEnabled( false ), myYGridMinorEnabled( false ),
103        myXGridMaxMajor( 8 ), myYGridMaxMajor( 8 ), myXGridMaxMinor( 5 ), myYGridMaxMinor( 5 ),
104        myXMode( 0 ), myYMode( 0 )
105        
106 {
107   myCurves.setAutoDelete( true );
108   /* Plot 2d View */
109   myPlot = new Plot2d_Plot2d( this );
110   setCentralWidget( myPlot );
111
112   createActions();
113
114   connect( myPlot, SIGNAL( plotMouseMoved( const QMouseEvent& ) ),
115            this,   SLOT( plotMouseMoved( const QMouseEvent& ) ) );
116   connect( myPlot, SIGNAL( plotMousePressed( const QMouseEvent& ) ),
117            this,   SLOT( plotMousePressed( const QMouseEvent& ) ) );
118   connect( myPlot, SIGNAL( plotMouseReleased( const QMouseEvent& ) ),
119            this,   SLOT( plotMouseReleased( const QMouseEvent& ) ) );
120   connect( myPlot, SIGNAL( legendClicked( long ) ),
121            this,   SLOT( onLegendClicked( long ) ) );
122
123   /* Initial Setup - get from the preferences */
124   readPreferences();
125
126   myPlot->setMargin( 5 );
127   setCurveType( myCurveType, false );
128   setXGrid( myXGridMajorEnabled, myXGridMaxMajor, myXGridMinorEnabled, myXGridMaxMinor, false );
129   setYGrid( myYGridMajorEnabled, myYGridMaxMajor, myYGridMinorEnabled, myYGridMaxMinor, false );
130   setMainTitle( myTitleEnabled, myTitle, false );
131   setXTitle( myXTitleEnabled, myXTitle, false );
132   setYTitle( myYTitleEnabled, myYTitle, false );
133   setHorScaleMode( myXMode, false );
134   setVerScaleMode( myYMode, false );
135   setBackgroundColor( myBackground );
136   setLegendPos( myLegendPos );
137   showLegend( myShowLegend, false );
138   myPlot->replot();
139
140   if ( parent ) {
141     resize( (int)(0.8 * parent->width()), (int)(0.8 * parent->height()) );
142   }
143 }
144 /*!
145   Destructor
146 */
147 Plot2d_ViewFrame::~Plot2d_ViewFrame()
148 {
149   myActions.clear();
150   qApp->removeEventFilter( this );
151 }
152 /*!
153   Creates popup menu actions
154 */
155 void Plot2d_ViewFrame::createActions()
156 {
157   QAD_ResourceMgr* rmgr = QAD_Desktop::getResourceManager();
158   /* Linear/logarithmic mode */
159   // Horizontal axis
160   QActionPGroup* modeHorGrp = new QActionPGroup( this );
161   modeHorGrp->setExclusive( TRUE );
162   QActionP* linearXAction = new QActionP ( tr( "TOT_PLOT2D_MODE_LINEAR_HOR"),
163                                          rmgr->loadPixmap( "SALOMEGUI", tr("ICON_PLOT2D_MODE_LINEAR_HOR") ) ,
164                                          tr( "MEN_PLOT2D_MODE_LINEAR_HOR" ), 0, modeHorGrp );
165   linearXAction->setStatusTip ( tr( "PRP_PLOT2D_MODE_LINEAR_HOR" ) );
166   linearXAction->setToggleAction( true );
167   myActions.insert( ModeXLinearId, linearXAction );
168   QActionP* logXAction = new QActionP ( tr( "TOT_PLOT2D_MODE_LOGARITHMIC_HOR"),
169                                       rmgr->loadPixmap( "SALOMEGUI", tr("ICON_PLOT2D_MODE_LOGARITHMIC_HOR") ) ,
170                                       tr( "MEN_PLOT2D_MODE_LOGARITHMIC_HOR" ), 0, modeHorGrp );
171   logXAction->setStatusTip ( tr( "PRP_PLOT2D_MODE_LOGARITHMIC_HOR" ) );
172   logXAction->setToggleAction( true );
173   myActions.insert( ModeXLogarithmicId, logXAction );
174   connect( modeHorGrp, SIGNAL( selected( QActionP* ) ), this, SLOT( onHorMode() ) );
175
176   // Vertical axis
177   QActionPGroup* modeVerGrp = new QActionPGroup( this );
178   modeVerGrp->setExclusive( TRUE );
179   QActionP* linearYAction = new QActionP ( tr( "TOT_PLOT2D_MODE_LINEAR_VER"),
180                                          rmgr->loadPixmap( "SALOMEGUI", tr("ICON_PLOT2D_MODE_LINEAR_VER") ) ,
181                                          tr( "MEN_PLOT2D_MODE_LINEAR_VER" ), 0, modeVerGrp );
182   linearYAction->setStatusTip ( tr( "PRP_PLOT2D_MODE_LINEAR_VER" ) );
183   linearYAction->setToggleAction( true );
184   myActions.insert( ModeYLinearId, linearYAction );
185   QActionP* logYAction = new QActionP ( tr( "TOT_PLOT2D_MODE_LOGARITHMIC_VER"),
186                                       rmgr->loadPixmap( "SALOMEGUI", tr("ICON_PLOT2D_MODE_LOGARITHMIC_VER") ) ,
187                                       tr( "MEN_PLOT2D_MODE_LOGARITHMIC_VER" ), 0, modeVerGrp );
188   logYAction->setStatusTip ( tr( "PRP_PLOT2D_MODE_LOGARITHMIC_VER" ) );
189   logYAction->setToggleAction( true );
190   myActions.insert( ModeYLogarithmicId, logYAction );
191   connect( modeVerGrp, SIGNAL( selected( QActionP* ) ), this, SLOT( onVerMode() ) );
192
193   /* Legend */
194   QActionP* legendAction = new QActionP ( tr( "TOT_PLOT2D_SHOW_LEGEND"),
195                                         rmgr->loadPixmap( "SALOMEGUI", tr("ICON_PLOT2D_SHOW_LEGEND") ) ,
196                                         tr( "MEN_PLOT2D_SHOW_LEGEND" ), 0, this );
197   legendAction->setStatusTip ( tr( "PRP_PLOT2D_SHOW_LEGEND" ) );
198   legendAction->setToggleAction( true );
199   myActions.insert( LegendId, legendAction );
200   connect( legendAction, SIGNAL( activated() ), this, SLOT( onLegend() ) );
201
202   /* Curve type */
203   QActionPGroup* curveGrp = new QActionPGroup( this );
204   curveGrp->setExclusive( TRUE );
205   QActionP* pointsAction = new QActionP ( tr( "TOT_PLOT2D_CURVES_POINTS"),
206                                         rmgr->loadPixmap( "SALOMEGUI", tr("ICON_PLOT2D_CURVES_POINTS") ) ,
207                                         tr( "MEN_PLOT2D_CURVES_POINTS" ), 0, curveGrp );
208   pointsAction->setStatusTip ( tr( "PRP_PLOT2D_CURVES_POINTS" ) );
209   pointsAction->setToggleAction( true );
210   myActions.insert( CurvePointsId, pointsAction );
211   QActionP* linesAction = new QActionP ( tr( "TOT_PLOT2D_CURVES_LINES"),
212                                        rmgr->loadPixmap( "SALOMEGUI", tr("ICON_PLOT2D_CURVES_LINES") ) ,
213                                        tr( "MEN_PLOT2D_CURVES_LINES" ), 0, curveGrp );
214   linesAction->setStatusTip ( tr( "PRP_PLOT2D_CURVES_LINES" ) );
215   linesAction->setToggleAction( true );
216   myActions.insert( CurveLinesId, linesAction );
217   QActionP* splinesAction = new QActionP ( tr( "TOT_PLOT2D_CURVES_SPLINES"),
218                                          rmgr->loadPixmap( "SALOMEGUI", tr("ICON_PLOT2D_CURVES_SPLINES") ) ,
219                                          tr( "MEN_PLOT2D_CURVES_SPLINES" ), 0, curveGrp );
220   splinesAction->setStatusTip ( tr( "PRP_PLOT2D_CURVES_SPLINES" ) );
221   splinesAction->setToggleAction( true );
222   myActions.insert( CurveSplinesId, splinesAction );
223   connect( curveGrp, SIGNAL( selected( QActionP* ) ), this, SLOT( onCurves() ) );
224
225   // Settings
226   QActionP* settingsAction = new QActionP ( tr( "TOT_PLOT2D_SETTINGS"),
227                                           rmgr->loadPixmap( "SALOMEGUI", tr("ICON_PLOT2D_SETTINGS") ) ,
228                                           tr( "MEN_PLOT2D_SETTINGS" ), 0, this );
229   settingsAction->setStatusTip ( tr( "PRP_PLOT2D_SETTINGS" ) );
230   myActions.insert( SettingsId, settingsAction );
231   connect( settingsAction, SIGNAL( activated() ), this, SLOT( onSettings() ) );
232
233   // Fit Data
234   QActionP* fitDataAction = new QActionP ( tr( "TOT_PLOT2D_FITDATA"),
235                                          rmgr->loadPixmap( "SALOMEGUI", tr("ICON_PLOT2D_FITDATA") ) ,
236                                          tr( "MEN_PLOT2D_FITDATA" ), 0, this );
237   fitDataAction->setStatusTip ( tr( "PRP_PLOT2D_FITDATA" ) );
238   myActions.insert( FitDataId, fitDataAction );
239   connect( fitDataAction, SIGNAL( activated() ), this, SLOT( onFitData() ) );
240
241   // Change background
242   QActionP* changeBGAction = new QActionP ( tr( "TOT_PLOT2D_CHANGE_BACKGROUND"),
243                                             tr( "MEN_PLOT2D_CHANGE_BACKGROUND" ), 0, this );
244   fitDataAction->setStatusTip ( tr( "PRP_PLOT2D_CHANGE_BACKGROUND" ) );
245   myActions.insert( ChangeBackgroundId, changeBGAction );
246   connect( changeBGAction, SIGNAL( activated() ), this, SLOT( onChangeBackground() ) );
247 }
248 /*!
249   Gets window's central widget
250 */
251 QWidget* Plot2d_ViewFrame::getViewWidget()
252 {
253   return (QWidget*)myPlot;
254 }
255 /* Popup management : sets Popup server */
256 void Plot2d_ViewFrame::setPopupServer( QAD_Application* App )
257 {
258 //  QAD_PopupClientServer::setPopupServer( (QAD_PopupServer*)App );
259 }
260 /*!
261   Popup menu creation
262 */
263 void Plot2d_ViewFrame::onCreatePopup()
264 {
265   if ( myPopup ) {
266     myPopup->clear();
267     // scaling
268     QPopupMenu* scalingPopup = new QPopupMenu( myPopup );
269     myActions[ ModeXLinearId ]->addTo( scalingPopup );
270     myActions[ ModeXLogarithmicId ]->addTo( scalingPopup );
271     scalingPopup->insertSeparator();
272     myActions[ ModeYLinearId ]->addTo( scalingPopup );
273     myActions[ ModeYLogarithmicId ]->addTo( scalingPopup );
274     myActions[ FitDataId ]->addTo( myPopup );
275     myPopup->insertItem( tr( "SCALING_POPUP" ), scalingPopup );
276     // curve type
277     QPopupMenu* curTypePopup = new QPopupMenu( myPopup );
278     myActions[ CurvePointsId ]->addTo( curTypePopup );
279     myActions[ CurveLinesId ]->addTo( curTypePopup );
280     myActions[ CurveSplinesId ]->addTo( curTypePopup );
281     myPopup->insertItem( tr( "CURVE_TYPE_POPUP" ), curTypePopup );
282     // legend
283     myPopup->insertSeparator();
284     myActions[ LegendId ]->addTo( myPopup );
285     // settings
286     myPopup->insertSeparator();
287     myActions[ SettingsId ]->addTo( myPopup );
288     // Change background
289     myPopup->insertSeparator();
290     myActions[ ChangeBackgroundId ]->addTo( myPopup );
291   }
292 }
293 /*!
294   Renames curve if it is found
295 */
296 void Plot2d_ViewFrame::rename( const Handle(SALOME_InteractiveObject)& IObject, QString newName ) 
297 {
298   Plot2d_Curve* curve = getCurveByIO( IObject );
299   if ( curve ) {
300     curve->setVerTitle( newName );
301     int key = hasCurve( curve );
302     if ( key ) {
303       myPlot->setCurveTitle( key, newName );
304 //      int legendIndex = myPlot->getLegend()->findFirstKey( key );
305 //      if ( legendIndex != myPlot->getLegend()->itemCnt() )
306 //      myPlot->getLegend()->setText( legendIndex, aSymbol );
307     }
308   }
309   updateTitles();
310 }
311 /*!
312   Returns true if interactive object is presented in the viewer
313 */
314 bool Plot2d_ViewFrame::isInViewer( const Handle(SALOME_InteractiveObject)& IObject ) 
315 {
316   if( getCurveByIO( IObject ) != NULL )
317     return 1;
318   else{
319     if(!IObject.IsNull()){
320       QIntDictIterator<Plot2d_Curve> it(myCurves);
321       for(; it.current();++it){
322         if(it.current()->hasIO() && it.current()->getTableIO()->isSame(IObject))
323           return 1;
324       }}
325   }
326   return 0;
327 }
328 /*!
329   Returns true if interactive object is presented in the viewer and displayed
330 */
331 bool Plot2d_ViewFrame::isVisible( const Handle(SALOME_InteractiveObject)& IObject ) 
332 {
333   Plot2d_Curve* curve = getCurveByIO( IObject );
334   if ( curve ) {
335     int key = hasCurve( curve );
336     if ( key )
337       return myPlot->curve( key )->enabled();
338   }
339   return false;
340 }
341 /*!
342   Return interactive obeject if is presented in the viewer
343 */
344 Handle(SALOME_InteractiveObject) Plot2d_ViewFrame::FindIObject( const char* Entry )
345 {
346   Handle(SALOME_InteractiveObject) o;
347   QIntDictIterator<Plot2d_Curve> it( myCurves );
348   for ( ; it.current(); ++it ) {
349     if ( it.current()->hasIO() && !strcmp( it.current()->getIO()->getEntry(), Entry ) ) {
350       o = it.current()->getIO();
351       break;
352     }
353   }
354   return o;
355 }
356 /*!
357   Actually this method just re-displays curves which refers to the <IObject>
358 */
359 void Plot2d_ViewFrame::Display( const Handle(SALOME_InteractiveObject)& IObject, bool update )
360 {
361   Plot2d_Curve* curve = getCurveByIO( IObject );
362   if ( curve )
363     updateCurve( curve, update );
364 }
365 /*!
366   Actually this method just erases all curves which don't refer to <IOBject> 
367   and re-displays curve which is of <IObject>
368 */
369 void Plot2d_ViewFrame::DisplayOnly( const Handle(SALOME_InteractiveObject)& IObject )
370 {
371   Plot2d_Curve* curve = getCurveByIO( IObject );
372   QList<Plot2d_Curve> clist;
373   getCurves( clist );
374   for ( int i = 0; i < clist.count(); i++ ) {
375     if ( clist.at( i ) != curve )
376       eraseCurve( curve );
377     else
378       updateCurve( curve, false );
379   }
380   myPlot->replot();
381 }
382 /*!
383   Removes from the viewer the curves which refer to <IObject>
384 */
385 void Plot2d_ViewFrame::Erase( const Handle(SALOME_InteractiveObject)& IObject, bool update )
386 {
387   Plot2d_Curve* curve = getCurveByIO( IObject );
388   if ( curve )
389     eraseCurve( curve, update );
390   // it can be table or container object selected
391   QAD_Study* activeStudy = QAD_Application::getDesktop()->getActiveStudy();
392   SALOMEDS::SObject_var aSO = activeStudy->getStudyDocument()->FindObjectID(IObject->getEntry());
393   if ( !aSO->_is_nil() ) {
394     SALOMEDS::ChildIterator_var aIter = activeStudy->getStudyDocument()->NewChildIterator( aSO );
395     for ( ; aIter->More(); aIter->Next() ) {
396       SALOMEDS::SObject_var aChildSO = aIter->Value();
397       SALOMEDS::SObject_var refSO;
398       if ( aChildSO->ReferencedObject( refSO ) && !refSO->_is_nil() )
399         aChildSO = refSO;
400       curve = getCurveByIO( new SALOME_InteractiveObject( aChildSO->GetID(), "", "" ) );
401       if ( curve )
402         eraseCurve( curve, update );
403     }
404   }
405 }
406 /*!
407   Actually this method just re-displays all curves which are presented in the viewer
408 */
409 void Plot2d_ViewFrame::DisplayAll()
410 {
411   QList<Plot2d_Curve> clist;
412   getCurves( clist );
413   for ( int i = 0; i < clist.count(); i++ ) {
414     updateCurve( clist.at( i ), false );
415    }
416   myPlot->replot();
417 }
418 /*!
419    Removes all curves from the view
420 */
421 void Plot2d_ViewFrame::EraseAll() 
422 {
423   myPlot->clear();
424   myCurves.clear();
425   myPlot->replot();
426 }
427 /*!
428   Redraws viewframe contents
429 */
430 void Plot2d_ViewFrame::Repaint()
431 {
432   myPlot->replot();
433 }
434 /*!
435   Event filter
436 */
437 bool Plot2d_ViewFrame::eventFilter( QObject* o, QEvent* e )
438 {
439   if ( ( e->type() == QEvent::MouseButtonPress || e->type() == QEvent::KeyPress ) && o != myPlot->canvas() ) {
440     myOperation = NoOpId;
441     qApp->removeEventFilter( this );
442   }
443   return QMainWindow::eventFilter( o, e );
444 }
445 /*!
446   Sets title
447 */
448 void Plot2d_ViewFrame::setTitle( const QString& title )
449 {
450   setMainTitle( myTitleEnabled, title, true );
451 }
452 /*!
453   Reads Plot2d view settings from the preferences
454 */
455 void Plot2d_ViewFrame::readPreferences()
456 {
457   if ( QAD_CONFIG->hasSetting( "Plot2d:CurveType" ) ) {                                          // curve type
458     myCurveType = QAD_CONFIG->getSetting( "Plot2d:CurveType" ).toInt();                             
459     if ( myCurveType < 0 || myCurveType > 2 ) myCurveType = 1;
460   }
461   if ( QAD_CONFIG->hasSetting( "Plot2d:ShowLegend" ) ) {                                          
462     myShowLegend = QAD_CONFIG->getSetting( "Plot2d:ShowLegend" ) == QString( "true" );           // show legend
463   }
464   if ( QAD_CONFIG->hasSetting( "Plot2d:LegendPos" ) ) {                                          // legend position
465     myLegendPos  = QAD_CONFIG->getSetting( "Plot2d:LegendPos" ).toInt();                            
466     if ( myLegendPos < 0 || myLegendPos > 3 ) myLegendPos = 1;
467   }
468   if ( QAD_CONFIG->hasSetting( "Plot2d:MarkerSize" ) ) {                                         // marker size
469     myMarkerSize = QAD_CONFIG->getSetting( "Plot2d:MarkerSize" ).toInt();                           
470   }
471   if ( QAD_CONFIG->hasSetting( "Plot2d:Background" ) ) {                                         // background color
472     QString bgString = QAD_CONFIG->getSetting( "Plot2d:Background" );                               
473     QStringList bgData = QStringList::split( ":", bgString, true );
474     int bgRed = 0, bgGreen = 0, bgBlue = 0;
475     if ( bgData.count() > 0 ) bgRed   = bgData[ 0 ].toInt();
476     if ( bgData.count() > 1 ) bgGreen = bgData[ 1 ].toInt();
477     if ( bgData.count() > 2 ) bgBlue  = bgData[ 2 ].toInt();
478     myBackground = QColor( bgRed, bgGreen, bgBlue );
479   }
480   if ( QAD_CONFIG->hasSetting( "Plot2d:ShowTitle" ) ) {                                          // main title
481     myTitleEnabled  = QAD_CONFIG->getSetting( "Plot2d:ShowTitle" ) == QString( "true" );               
482   }
483   if ( QAD_CONFIG->hasSetting( "Plot2d:ShowHorTitle" ) ) {                                       // hor.axis title
484     myXTitleEnabled = QAD_CONFIG->getSetting( "Plot2d:ShowHorTitle" ) == QString( "true" );
485   }
486   if ( QAD_CONFIG->hasSetting( "Plot2d:ShowVerTitle" ) ) {                                       // ver.axisn title
487     myYTitleEnabled = QAD_CONFIG->getSetting( "Plot2d:ShowVerTitle" ) == QString( "true" );
488   }
489   if ( QAD_CONFIG->hasSetting( "Plot2d:EnableHorMajorGrid" ) ) {                                 // grid
490     myXGridMajorEnabled = QAD_CONFIG->getSetting( "Plot2d:EnableHorMajorGrid" ) == QString( "true" ); 
491   }
492   if ( QAD_CONFIG->hasSetting( "Plot2d:EnableVerMajorGrid" ) ) {      
493     myYGridMajorEnabled = QAD_CONFIG->getSetting( "Plot2d:EnableVerMajorGrid" ) == QString( "true" );
494   }
495   if ( QAD_CONFIG->hasSetting( "Plot2d:EnableHorMinorGrid" ) ) {
496     myXGridMinorEnabled = QAD_CONFIG->getSetting( "Plot2d:EnableHorMinorGrid" ) == QString( "true" );
497   }
498   if ( QAD_CONFIG->hasSetting( "Plot2d:EnableVerMinorGrid" ) ) {
499     myYGridMinorEnabled = QAD_CONFIG->getSetting( "Plot2d:EnableVerMinorGrid" ) == QString( "true" );
500   }
501   if ( QAD_CONFIG->hasSetting( "Plot2d:HorMajorGridMax" ) ) {
502     myXGridMaxMajor = QAD_CONFIG->getSetting( "Plot2d:HorMajorGridMax" ).toInt();
503   }
504   if ( QAD_CONFIG->hasSetting( "Plot2d:VerMajorGridMax" ) ) {
505     myYGridMaxMajor = QAD_CONFIG->getSetting( "Plot2d:VerMajorGridMax" ).toInt();
506   }
507   if ( QAD_CONFIG->hasSetting( "Plot2d:HorMinorGridMax" ) ) {
508     myXGridMaxMinor = QAD_CONFIG->getSetting( "Plot2d:HorMinorGridMax" ).toInt();
509   }
510   if ( QAD_CONFIG->hasSetting( "Plot2d:VerMinorGridMax" ) ) {
511     myYGridMaxMinor = QAD_CONFIG->getSetting( "Plot2d:VerMinorGridMax" ).toInt();
512   }
513   if ( QAD_CONFIG->hasSetting( "Plot2d:HorScaleMode" ) ) {                                       // scale mode
514     myXMode = QAD_CONFIG->getSetting( "Plot2d:HorScaleMode" ).toInt();                             
515     if ( myXMode < 0 || myXMode > 1 ) myXMode = 0;
516   }
517   if ( QAD_CONFIG->hasSetting( "Plot2d:VerScaleMode" ) ) {                                       
518     myYMode = QAD_CONFIG->getSetting( "Plot2d:VerScaleMode" ).toInt();
519     if ( myYMode < 0 || myYMode > 1 ) myYMode = 0;
520   }
521 }
522 /*!
523   Writes Plot2d view settings to the preferences
524 */
525 void Plot2d_ViewFrame::writePreferences()
526 {
527   QAD_CONFIG->addSetting( "Plot2d:CurveType",  myCurveType );                                     // curve type
528   QAD_CONFIG->addSetting( "Plot2d:ShowLegend", myShowLegend ? "true" : "false" );                 // show legend
529   QAD_CONFIG->addSetting( "Plot2d:LegendPos",  myLegendPos );                                     // legend position
530   QAD_CONFIG->addSetting( "Plot2d:MarkerSize", myMarkerSize );                                    // marker size
531   QStringList bgData; 
532   bgData.append( QString::number( myBackground.red() ) );
533   bgData.append( QString::number( myBackground.green() ) );
534   bgData.append( QString::number( myBackground.blue() ) );
535   QAD_CONFIG->addSetting( "Plot2d:Background",   bgData.join( ":" ) );                            // background color
536   QAD_CONFIG->addSetting( "Plot2d:ShowTitle",    myTitleEnabled ?  "true" : "false" );            // titles
537   QAD_CONFIG->addSetting( "Plot2d:ShowHorTitle", myXTitleEnabled ? "true" : "false" ); 
538   QAD_CONFIG->addSetting( "Plot2d:ShowVerTitle", myYTitleEnabled ? "true" : "false" ); 
539   QAD_CONFIG->addSetting( "Plot2d:EnableHorMajorGrid", myXGridMajorEnabled ? "true" : "false" );  // grid
540   QAD_CONFIG->addSetting( "Plot2d:EnableVerMajorGrid", myYGridMajorEnabled ? "true" : "false" );  
541   QAD_CONFIG->addSetting( "Plot2d:EnableHorMinorGrid", myXGridMinorEnabled ? "true" : "false" );  
542   QAD_CONFIG->addSetting( "Plot2d:EnableVerMinorGrid", myYGridMinorEnabled ? "true" : "false" );  
543   QAD_CONFIG->addSetting( "Plot2d:HorMajorGridMax", myXGridMaxMajor );
544   QAD_CONFIG->addSetting( "Plot2d:VerMajorGridMax", myYGridMaxMajor );
545   QAD_CONFIG->addSetting( "Plot2d:HorMinorGridMax", myXGridMaxMinor );
546   QAD_CONFIG->addSetting( "Plot2d:VerMinorGridMax", myYGridMaxMinor );
547   QAD_CONFIG->addSetting( "Plot2d:HorScaleMode", myXMode );                                       // scale mode
548   QAD_CONFIG->addSetting( "Plot2d:VerScaleMode", myYMode );
549 }
550 /*!
551   Prints mouse cursor coordinates into string
552 */
553 QString Plot2d_ViewFrame::getInfo( const QPoint& pnt ) 
554 {
555   bool xFound = false, yFound = false;
556   double xCoord, yCoord;
557   const QwtScaleDiv* aXscale = myPlot->axisScale( QwtPlot::xBottom );
558   for ( int i = 0; i < aXscale->majCnt(); i++ ) {
559     double majXmark = aXscale->majMark( i );
560     int xmark = myPlot->transform( QwtPlot::xBottom, majXmark );
561     if ( xmark-2 == pnt.x() ) {
562       xCoord = majXmark; 
563       xFound = true;
564       MESSAGE("Plot2d_ViewFrame::getInfo : close maj X mark("<<i<<") = "<<majXmark<<" "<<xmark<<" "<<pnt.x());
565       break;
566     }
567   }
568   if ( !xFound ) {
569     for ( int i = 0; i < aXscale->minCnt(); i++ ) {
570       double minXmark = aXscale->minMark( i );
571       int xmark = myPlot->transform( QwtPlot::xBottom, minXmark );
572       if ( xmark-2 == pnt.x() ) {
573         xCoord = minXmark; 
574         xFound = true;
575         MESSAGE("Plot2d_ViewFrame::getInfo : close min X mark("<<i<<") = "<<minXmark<<" "<<xmark<<" "<<pnt.x());
576         break;
577       }
578     }
579   }  
580   const QwtScaleDiv* aYscale = myPlot->axisScale( QwtPlot::yLeft );
581   for ( int i = 0; i < aYscale->majCnt(); i++ ) {
582     double majYmark = aYscale->majMark( i );
583     int ymark = myPlot->transform( QwtPlot::yLeft, majYmark );
584     if ( ymark-2 == pnt.y() ) {
585       yCoord = majYmark; 
586       yFound = true;
587       break;
588     }
589   }
590   if ( !yFound ) {
591     for ( int i = 0; i < aYscale->minCnt(); i++ ) {
592       double minYmark = aYscale->minMark( i );
593       int ymark = myPlot->transform( QwtPlot::yLeft, minYmark );
594       if ( ymark-2 == pnt.y() ) {
595         yCoord = minYmark; 
596         yFound = true;
597         break;
598       }
599     }
600   }  
601   QString strX = QString::number( xFound ? xCoord : myPlot->invTransform( QwtPlot::xBottom, pnt.x() ) ).stripWhiteSpace();
602   if ( strX == "-0" )
603     strX = "0";
604   QString strY = QString::number( yFound ? yCoord : myPlot->invTransform( QwtPlot::yLeft, pnt.y() ) ).stripWhiteSpace();
605   if ( strY == "-0" )
606     strY = "0";
607   QString info = tr("INF_COORDINATES").arg( strX ).arg( strY );
608   return info;
609 }
610 /*!
611   Converts Plot2d_Curve's marker style to Qwt marker style [ static ]
612 */
613 static QwtSymbol::Style plot2qwtMarker( Plot2d_Curve::MarkerType m )
614 {
615   QwtSymbol::Style ms = QwtSymbol::None;  
616   switch ( m ) {
617   case Plot2d_Curve::Circle:
618     ms = QwtSymbol::Ellipse;   break;
619   case Plot2d_Curve::Rectangle:
620     ms = QwtSymbol::Rect;      break;
621   case Plot2d_Curve::Diamond:
622     ms = QwtSymbol::Diamond;   break;
623   case Plot2d_Curve::DTriangle:
624     ms = QwtSymbol::DTriangle; break;
625   case Plot2d_Curve::UTriangle:
626     ms = QwtSymbol::UTriangle; break;
627   case Plot2d_Curve::LTriangle: // Qwt confuses LTriangle and RTriangle :(((
628     ms = QwtSymbol::RTriangle; break;
629   case Plot2d_Curve::RTriangle: // Qwt confuses LTriangle and RTriangle :(((
630     ms = QwtSymbol::LTriangle; break;
631   case Plot2d_Curve::Cross:
632     ms = QwtSymbol::Cross;     break;
633   case Plot2d_Curve::XCross:
634     ms = QwtSymbol::XCross;    break;
635   case Plot2d_Curve::None:
636   default:
637     ms = QwtSymbol::None;      break;
638   }
639   return ms;
640 }
641 /*!
642   Converts Qwt marker style to Plot2d_Curve's marker style [ static ]
643 */
644 static Plot2d_Curve::MarkerType qwt2plotMarker( QwtSymbol::Style m )
645 {
646   Plot2d_Curve::MarkerType ms = Plot2d_Curve::None;  
647   switch ( m ) {
648   case QwtSymbol::Ellipse:
649     ms = Plot2d_Curve::Circle;    break;
650   case QwtSymbol::Rect:
651     ms = Plot2d_Curve::Rectangle; break;
652   case QwtSymbol::Diamond:
653     ms = Plot2d_Curve::Diamond;   break;
654   case QwtSymbol::DTriangle:
655     ms = Plot2d_Curve::DTriangle; break;
656   case QwtSymbol::UTriangle:
657     ms = Plot2d_Curve::UTriangle; break;
658   case QwtSymbol::RTriangle: // Qwt confuses LTriangle and RTriangle :(((
659     ms = Plot2d_Curve::LTriangle; break;
660   case QwtSymbol::LTriangle: // Qwt confuses LTriangle and RTriangle :(((
661     ms = Plot2d_Curve::RTriangle; break;
662   case QwtSymbol::Cross:
663     ms = Plot2d_Curve::Cross;     break;
664   case QwtSymbol::XCross:
665     ms = Plot2d_Curve::XCross;    break;
666   case QwtSymbol::None:
667   default:
668     ms = Plot2d_Curve::None;      break;
669   }
670   return ms;
671 }
672 /*!
673   Converts Plot2d_Curve's line style to Qwt line style [ static ]
674 */
675 static Qt::PenStyle plot2qwtLine( Plot2d_Curve::LineType p )
676 {
677   Qt::PenStyle ps = Qt::NoPen;
678   switch ( p ) {
679   case Plot2d_Curve::Solid:
680     ps = Qt::SolidLine;      break;
681   case Plot2d_Curve::Dash:
682     ps = Qt::DashLine;       break;
683   case Plot2d_Curve::Dot:
684     ps = Qt::DotLine;        break;
685   case Plot2d_Curve::DashDot:
686     ps = Qt::DashDotLine;    break;
687   case Plot2d_Curve::DashDotDot:
688     ps = Qt::DashDotDotLine; break;
689   case Plot2d_Curve::NoPen:
690   default:
691     ps = Qt::NoPen;          break;
692   }
693   return ps;
694 }
695 /*!
696   Converts Qwt line style to Plot2d_Curve's line style [ static ]
697 */
698 static Plot2d_Curve::LineType qwt2plotLine( Qt::PenStyle p )
699 {
700   Plot2d_Curve::LineType ps = Plot2d_Curve::NoPen;
701   switch ( p ) {
702   case Qt::SolidLine:
703     ps = Plot2d_Curve::Solid;      break;
704   case Qt::DashLine:
705     ps = Plot2d_Curve::Dash;       break;
706   case Qt::DotLine:
707     ps = Plot2d_Curve::Dot;        break;
708   case Qt::DashDotLine:
709     ps = Plot2d_Curve::DashDot;    break;
710   case Qt::DashDotDotLine:
711     ps = Plot2d_Curve::DashDotDot; break;
712   case Qt::NoPen:
713   default:
714     ps = Plot2d_Curve::NoPen;      break;
715   }
716   return ps;
717 }
718 /*!
719   Adds curve into view
720 */
721 void Plot2d_ViewFrame::displayCurve( Plot2d_Curve* curve, bool update )
722 {
723   if ( !curve )
724     return;
725   if ( hasCurve( curve ) ) {
726     updateCurve( curve, update );
727   }
728   else {
729     long curveKey = myPlot->insertCurve( curve->getVerTitle() );
730     myCurves.insert( curveKey, curve );
731     if ( curve->isAutoAssign() ) {
732       QwtSymbol::Style typeMarker;
733       QColor           color;
734       Qt::PenStyle     typeLine;
735       myPlot->getNextMarker( typeMarker, color, typeLine );
736       myPlot->setCurvePen( curveKey, QPen( color, DEFAULT_LINE_WIDTH, typeLine ) );
737       myPlot->setCurveSymbol( curveKey, QwtSymbol( typeMarker, 
738                                                    QBrush( color ), 
739                                                    QPen( color ), 
740                                                    QSize( myMarkerSize, myMarkerSize ) ) );
741       curve->setColor( color );
742       curve->setLine( qwt2plotLine( typeLine ) );
743       curve->setMarker( qwt2plotMarker( typeMarker ) );
744     }
745     else {
746       Qt::PenStyle     ps = plot2qwtLine( curve->getLine() );
747       QwtSymbol::Style ms = plot2qwtMarker( curve->getMarker() );
748       myPlot->setCurvePen( curveKey, QPen( curve->getColor(), curve->getLineWidth(), ps ) );
749       myPlot->setCurveSymbol( curveKey, QwtSymbol( ms, 
750                                                    QBrush( curve->getColor() ), 
751                                                    QPen( curve->getColor() ), 
752                                                    QSize( myMarkerSize, myMarkerSize ) ) );
753     }
754     if ( myCurveType == 0 )
755       myPlot->setCurveStyle( curveKey, QwtCurve::NoCurve );
756     else if ( myCurveType == 1 )
757       myPlot->setCurveStyle( curveKey, QwtCurve::Lines );
758     else if ( myCurveType == 2 )
759       myPlot->setCurveStyle( curveKey, QwtCurve::Spline );
760     myPlot->setCurveData( curveKey, curve->horData(), curve->verData(), curve->nbPoints() );
761   }
762   updateTitles();
763   if ( update )
764     myPlot->replot();
765 }
766 /*!
767   Adds curves into view
768 */
769 void Plot2d_ViewFrame::displayCurves( Plot2d_CurveContainer& curves, bool update )
770 {
771   myPlot->setUpdatesEnabled( false );
772   for ( int i = 0; i < curves.count(); i++ ) {
773     displayCurve( curves.curve( i ), false );
774   }
775 //  fitAll();
776   myPlot->setUpdatesEnabled( true );
777   if ( update )
778     myPlot->replot();
779 }
780 /*!
781   Erases curve
782 */
783 void Plot2d_ViewFrame::eraseCurve( Plot2d_Curve* curve, bool update )
784 {
785   if ( !curve )
786     return;
787   int curveKey = hasCurve( curve );
788   if ( curveKey ) {
789     myPlot->removeCurve( curveKey );
790     myCurves.remove( curveKey );
791     updateTitles();
792     if ( update )
793       myPlot->replot();
794   }
795 }
796 /*!
797   Erases curves
798 */
799 void Plot2d_ViewFrame::eraseCurves( Plot2d_CurveContainer& curves, bool update )
800 {
801   for ( int i = 0; i < curves.count(); i++ ) {
802     eraseCurve( curves.curve( i ), false );
803   }
804 //  fitAll();
805   if ( update )
806     myPlot->replot();
807 }
808 /*!
809   Updates curves attributes
810 */
811 void Plot2d_ViewFrame::updateCurve( Plot2d_Curve* curve, bool update )
812 {
813   if ( !curve )
814     return;
815   int curveKey = hasCurve( curve );
816   if ( curveKey ) {
817     if ( !curve->isAutoAssign() ) {
818       Qt::PenStyle     ps = plot2qwtLine( curve->getLine() );
819       QwtSymbol::Style ms = plot2qwtMarker( curve->getMarker() );
820       myPlot->setCurvePen( curveKey, QPen( curve->getColor(), curve->getLineWidth(), ps ) );
821       myPlot->setCurveSymbol( curveKey, QwtSymbol( ms, 
822                                                    QBrush( curve->getColor() ), 
823                                                    QPen( curve->getColor() ), 
824                                                    QSize( myMarkerSize, myMarkerSize ) ) );
825     }
826     myPlot->setCurveTitle( curveKey, curve->getVerTitle() );
827     myPlot->setCurveData( curveKey, curve->horData(), curve->verData(), curve->nbPoints() );
828     myPlot->curve( curveKey )->setEnabled( true );
829     updateTitles();
830     if ( update )
831       myPlot->replot();
832   }
833 }
834 /*!
835   Returns curve key if is is displayed in the viewer and 0 otherwise
836 */
837 int Plot2d_ViewFrame::hasCurve( Plot2d_Curve* curve )
838 {
839   QIntDictIterator<Plot2d_Curve> it( myCurves );
840   for ( ; it.current(); ++it ) {
841     if ( it.current() == curve )
842       return it.currentKey();
843   }
844   return 0;
845 }
846 Plot2d_Curve* Plot2d_ViewFrame::getCurveByIO( const Handle(SALOME_InteractiveObject)& theIObject )
847 {
848   if ( !theIObject.IsNull() ) {
849     QIntDictIterator<Plot2d_Curve> it( myCurves );
850     for ( ; it.current(); ++it ) {
851       if ( it.current()->hasIO() && it.current()->getIO()->isSame( theIObject ) )
852         return it.current();
853     }
854   }
855   return 0;
856 }
857 /*!
858   Gets lsit of displayed curves
859 */
860 int Plot2d_ViewFrame::getCurves( QList<Plot2d_Curve>& clist )
861 {
862   clist.clear();
863   clist.setAutoDelete( false );
864   QIntDictIterator<Plot2d_Curve> it( myCurves );
865   for ( ; it.current(); ++it ) {
866     clist.append( it.current() );
867   }
868   return clist.count();
869 }
870
871 /*!
872   Updates titles according to curves
873 */
874 #define BRACKETIZE(x) QString( "[ " ) + x + QString( " ]" )
875 void Plot2d_ViewFrame::updateTitles() 
876 {
877   QAD_Study* activeStudy = QAD_Application::getDesktop()->getActiveStudy();
878   QIntDictIterator<Plot2d_Curve> it( myCurves );
879   QStringList aXTitles;
880   QStringList aYTitles;
881   QStringList aXUnits;
882   QStringList aYUnits;
883   QStringList aTables;
884   int i = 0;
885   while ( it.current() ) {
886     // collect titles and units from all curves...
887     QString xTitle = it.current()->getHorTitle().stripWhiteSpace();
888     QString yTitle = it.current()->getVerTitle().stripWhiteSpace();
889     QString xUnits = it.current()->getHorUnits().stripWhiteSpace();
890     QString yUnits = it.current()->getVerUnits().stripWhiteSpace();
891     
892     aYTitles.append( yTitle );
893     if ( aXTitles.find( xTitle ) == aXTitles.end() )
894       aXTitles.append( xTitle );
895     if ( aXUnits.find( xUnits ) == aXUnits.end() )
896       aXUnits.append( xUnits );
897     if ( aYUnits.find( yUnits ) == aYUnits.end() )
898       aYUnits.append( yUnits );
899
900     if ( activeStudy && it.current()->hasTableIO() ) { 
901       SALOMEDS::SObject_var SO = activeStudy->getStudyDocument()->FindObjectID( it.current()->getTableIO()->getEntry() );
902       if ( !SO->_is_nil() ) {
903         SALOMEDS::GenericAttribute_var anAttr;
904         if ( SO->FindAttribute( anAttr, "AttributeName" ) ) {
905           SALOMEDS::AttributeName_var aNameAttr = SALOMEDS::AttributeName::_narrow( anAttr );
906           QString aName = aNameAttr->Value();
907           if ( !aName.isEmpty() && aTables.find( aName ) == aTables.end() )
908             aTables.append( aName );
909         }
910       }
911     }
912
913     ++it;
914     ++i;
915   }
916   // ... and update plot 2d view
917   QString xUnits, yUnits;
918   if ( aXUnits.count() == 1 && !aXUnits[0].isEmpty() )
919     xUnits = BRACKETIZE( aXUnits[0] );
920   if ( aYUnits.count() == 1 && !aYUnits[0].isEmpty())
921     yUnits = BRACKETIZE( aYUnits[0] );
922   QString xTitle, yTitle;
923   if ( aXTitles.count() == 1 && aXUnits.count() == 1 )
924     xTitle = aXTitles[0];
925   if ( aYTitles.count() == 1 )
926     yTitle = aYTitles[0];
927
928   if ( !xTitle.isEmpty() && !xUnits.isEmpty() )
929     xTitle += " ";
930   if ( !yTitle.isEmpty() && !yUnits.isEmpty() )
931     yTitle += " ";
932
933   setXTitle( myXTitleEnabled, xTitle + xUnits );
934   setYTitle( myYTitleEnabled, yTitle + yUnits );
935   setTitle( aTables.join("; ") );
936 }
937 /*!
938   Fits the view to see all data
939 */
940 void Plot2d_ViewFrame::fitAll()
941 {
942   myPlot->setAxisAutoScale( QwtPlot::yLeft );
943   myPlot->setAxisAutoScale( QwtPlot::xBottom );
944   myPlot->replot();
945 }
946 /*!
947   Fits the view to rectangle area (pixels)
948 */
949 void Plot2d_ViewFrame::fitArea( const QRect& area )
950 {
951   QRect rect = area.normalize();
952   if ( rect.width() < MIN_RECT_SIZE ) {
953     rect.setWidth( MIN_RECT_SIZE );
954     rect.setLeft( rect.left() - MIN_RECT_SIZE/2 );
955   }
956   if ( rect.height() < MIN_RECT_SIZE ) {
957     rect.setHeight( MIN_RECT_SIZE );
958     rect.setTop( rect.top() - MIN_RECT_SIZE/2 );
959   }
960   myPlot->setAxisScale( QwtPlot::yLeft, 
961                         myPlot->invTransform( QwtPlot::yLeft, rect.top() ), 
962                         myPlot->invTransform( QwtPlot::yLeft, rect.bottom() ) );
963   myPlot->setAxisScale( QwtPlot::xBottom, 
964                         myPlot->invTransform( QwtPlot::xBottom, rect.left() ), 
965                         myPlot->invTransform( QwtPlot::xBottom, rect.right() ) );
966   myPlot->replot();
967 }
968 /*!
969   Tests if it is necessary to start operation on mouse action
970 */
971 int Plot2d_ViewFrame::testOperation( const QMouseEvent& me )
972 {
973   int btn = me.button() | me.state();
974   int zoomBtn = ControlButton | LeftButton;
975   int panBtn  = ControlButton | MidButton;
976   int fitBtn  = ControlButton | RightButton;
977
978   if ( btn == zoomBtn )
979     return ZoomId;
980   if ( btn == panBtn ) 
981     return PanId;
982   if ( btn == fitBtn )
983     return FitAreaId;
984   return NoOpId;
985 }
986 /*!
987   Mode toolbar buttons slot - horizontal axis (<Linear>/<Logarithmic>)
988 */
989 void Plot2d_ViewFrame::onHorMode()
990 {
991   if ( myActions[ ModeXLinearId ]->isOn() )
992     setHorScaleMode( 0 );
993   else if ( myActions[ ModeXLogarithmicId ]->isOn() )
994     setHorScaleMode( 1 );
995 }
996 /*!
997   Mode toolbar buttons slot - vertical axis (<Linear>/<Logarithmic>)
998 */
999 void Plot2d_ViewFrame::onVerMode()
1000 {
1001   if ( myActions[ ModeYLinearId ]->isOn() )
1002     setVerScaleMode( 0 );
1003   else if ( myActions[ ModeYLogarithmicId ]->isOn() )
1004     setVerScaleMode( 1 );
1005 }
1006 /*!
1007   "Show/hide legend" toolbar action slot
1008 */
1009 void Plot2d_ViewFrame::onLegend()
1010 {
1011   showLegend( myActions[ LegendId ]->isOn() );
1012 }
1013 /*!
1014   "Curve type" toolbar action slot
1015 */
1016 void Plot2d_ViewFrame::onCurves()
1017 {
1018   if ( myActions[ CurvePointsId ]->isOn() )
1019     setCurveType( 0 );
1020   else if ( myActions[ CurveLinesId ]->isOn() )
1021     setCurveType( 1 );
1022   else if ( myActions[ CurveSplinesId ]->isOn() )
1023     setCurveType( 2 );
1024 }
1025 /*!
1026   "Settings" toolbar action slot
1027 */
1028 void Plot2d_ViewFrame::onSettings()
1029 {
1030 #ifdef TEST_AUTOASSIGN
1031   typedef QMap<int,int> IList;
1032   typedef QMap<QString,int> SList;
1033   IList mars, lins;
1034   SList cols;
1035   cols[ "red-min" ]   = 1000;
1036   cols[ "red-max" ]   = -1;
1037   cols[ "green-min" ] = 1000;
1038   cols[ "green-max" ] = -1;
1039   cols[ "blue-min" ]  = 1000;
1040   cols[ "blue-max" ]  = -1;
1041   for ( unsigned i = 0; i < 10000; i++ ) {
1042     QwtSymbol::Style typeMarker;
1043     QColor           color;
1044     Qt::PenStyle     typeLine;
1045     myPlot->getNextMarker( typeMarker, color, typeLine );
1046     if ( mars.contains(typeMarker) )
1047       mars[ typeMarker ] = mars[ typeMarker ]+1;
1048     else
1049       mars[ typeMarker ] = 0;
1050     if ( lins.contains(typeLine) )
1051       lins[ typeLine ] = lins[ typeLine ]+1;
1052     else
1053       lins[ typeLine ] = 0;
1054     if ( cols[ "red-max" ] < color.red() )
1055       cols[ "red-max" ] = color.red();
1056     if ( cols[ "red-min" ] > color.red() )
1057       cols[ "red-min" ] = color.red();
1058     if ( cols[ "green-max" ] < color.green() )
1059       cols[ "green-max" ] = color.green();
1060     if ( cols[ "green-min" ] > color.green() )
1061       cols[ "green-min" ] = color.green();
1062     if ( cols[ "blue-max" ] < color.blue() )
1063       cols[ "blue-max" ] = color.blue();
1064     if ( cols[ "blue-min" ] > color.blue() )
1065       cols[ "blue-min" ] = color.blue();
1066   }
1067   for (IList::Iterator it = mars.begin();  it != mars.end(); ++it)
1068     MESSAGE("markers( " << it.key() << ") = " << it.data() );
1069   for (IList::Iterator it = lins.begin();  it != lins.end(); ++it)
1070     MESSAGE("lines( " << it.key() << ") = " << it.data() );
1071   for (SList::Iterator it = cols.begin();  it != cols.end(); ++it)
1072     MESSAGE("colors( " << it.key() << ") = " << it.data() );
1073 #endif
1074   
1075   Plot2d_SetupViewDlg* dlg = new Plot2d_SetupViewDlg( this, true );
1076   dlg->setMainTitle( myTitleEnabled, myTitle );
1077   dlg->setXTitle( myXTitleEnabled, myXTitle );
1078   dlg->setYTitle( myYTitleEnabled, myYTitle );
1079   dlg->setCurveType( myCurveType );
1080   dlg->setLegend( myShowLegend, myLegendPos );
1081   dlg->setMarkerSize( myMarkerSize );
1082   dlg->setBackgroundColor( myBackground );
1083   dlg->setMajorGrid( myXGridMajorEnabled, myPlot->axisMaxMajor( QwtPlot::xBottom ),
1084                      myYGridMajorEnabled, myPlot->axisMaxMajor( QwtPlot::yLeft ) );
1085   dlg->setMinorGrid( myXGridMinorEnabled, myPlot->axisMaxMinor( QwtPlot::xBottom ),
1086                      myYGridMinorEnabled, myPlot->axisMaxMinor( QwtPlot::yLeft ) );
1087   dlg->setScaleMode( myXMode, myYMode );
1088
1089   if ( dlg->exec() == QDialog::Accepted ) {
1090     // horizontal axis title
1091     setXTitle( dlg->isXTitleEnabled(), dlg->getXTitle(), false );
1092     // vertical axis title
1093     setYTitle( dlg->isYTitleEnabled(), dlg->getYTitle(), false );
1094     // main title
1095     setMainTitle( dlg->isMainTitleEnabled(), dlg->getMainTitle(), true );
1096     // curve type
1097     if ( myCurveType != dlg->getCurveType() ) {
1098       setCurveType( dlg->getCurveType(), false );
1099     }
1100     // legend
1101     if ( myShowLegend != dlg->isLegendEnabled() ) {
1102       showLegend( dlg->isLegendEnabled(), false );
1103     }
1104     if ( myLegendPos != dlg->getLegendPos() ) {
1105       setLegendPos( dlg->getLegendPos() );
1106     }
1107     // marker size
1108     if ( myMarkerSize != dlg->getMarkerSize() ) {
1109       setMarkerSize( dlg->getMarkerSize(), false );
1110     }
1111     // background color
1112     if ( myBackground != dlg->getBackgroundColor() ) {
1113       setBackgroundColor( dlg->getBackgroundColor() );
1114     }
1115     // grid
1116     bool aXGridMajorEnabled, aXGridMinorEnabled, aYGridMajorEnabled, aYGridMinorEnabled;
1117     int  aXGridMaxMajor,     aXGridMaxMinor,     aYGridMaxMajor,     aYGridMaxMinor;
1118     dlg->getMajorGrid( aXGridMajorEnabled, aXGridMaxMajor, aYGridMajorEnabled, aYGridMaxMajor );
1119     dlg->getMinorGrid( aXGridMinorEnabled, aXGridMaxMinor, aYGridMinorEnabled, aYGridMaxMinor );
1120     setXGrid( aXGridMajorEnabled, aXGridMaxMajor, aXGridMinorEnabled, aXGridMaxMinor, false );
1121     setYGrid( aYGridMajorEnabled, aYGridMaxMajor, aYGridMinorEnabled, aYGridMaxMinor, false );
1122     // scale mode
1123     if ( myXMode != dlg->getXScaleMode() ) {
1124       setHorScaleMode( dlg->getXScaleMode() );
1125     }
1126     if ( myYMode != dlg->getYScaleMode() ) {
1127       setVerScaleMode( dlg->getYScaleMode() );
1128     }
1129     // update view
1130     myPlot->replot();
1131     // update preferences
1132     if ( dlg->isSetAsDefault() ) 
1133       writePreferences();
1134   }
1135   delete dlg;
1136 }
1137 /*!
1138   "Fit Data" command slot
1139 */
1140 void Plot2d_ViewFrame::onFitData()
1141 {
1142   Plot2d_FitDataDlg* dlg = new Plot2d_FitDataDlg( this );
1143   int ixMin = myPlot->canvasMap( QwtPlot::xBottom ).i1();
1144   int ixMax = myPlot->canvasMap( QwtPlot::xBottom ).i2();
1145   int iyMin = myPlot->canvasMap( QwtPlot::yLeft ).i1();
1146   int iyMax = myPlot->canvasMap( QwtPlot::yLeft ).i2();
1147   double xMin = myPlot->invTransform(QwtPlot::xBottom, ixMin);
1148   double xMax = myPlot->invTransform(QwtPlot::xBottom, ixMax);
1149   double yMin = myPlot->invTransform(QwtPlot::yLeft, iyMin);
1150   double yMax = myPlot->invTransform(QwtPlot::yLeft, iyMax);
1151   
1152   dlg->setRange( xMin, xMax, yMin, yMax );
1153   if ( dlg->exec() == QDialog::Accepted ) {
1154     int mode = dlg->getRange( xMin, xMax, yMin, yMax );
1155     if ( mode == 0 || mode == 2 ) 
1156       myPlot->setAxisScale( QwtPlot::yLeft, yMax, yMin );
1157     if ( mode == 0 || mode == 1 ) 
1158       myPlot->setAxisScale( QwtPlot::xBottom, xMin, xMax ); 
1159     myPlot->replot();
1160   }
1161   delete dlg;
1162 }
1163 /*!
1164   Change background color
1165 */
1166 void Plot2d_ViewFrame::onChangeBackground()
1167 {
1168   QColor selColor = QColorDialog::getColor ( backgroundColor(), this ); 
1169   if ( selColor.isValid() ) {
1170     setBackgroundColor( selColor );
1171   }
1172 }
1173 /*!
1174   Sets curve type
1175 */
1176 void Plot2d_ViewFrame::setCurveType( int curveType, bool update )
1177 {
1178   myCurveType = curveType;
1179   if ( curveType == 0 )
1180     myActions[ CurvePointsId ]->setOn( true );
1181   else if ( curveType == 1 )
1182     myActions[ CurveLinesId ]->setOn( true );
1183   else if ( curveType == 2 )
1184     myActions[ CurveSplinesId ]->setOn( true );
1185   
1186   QArray<long> keys = myPlot->curveKeys();
1187   for ( int i = 0; i < keys.count(); i++ ) {
1188     if ( myCurveType == 0 )
1189       myPlot->setCurveStyle( keys[i], QwtCurve::NoCurve );
1190     else if ( myCurveType == 1 )
1191       myPlot->setCurveStyle( keys[i], QwtCurve::Lines );
1192     else if ( myCurveType == 2 )
1193       myPlot->setCurveStyle( keys[i], QwtCurve::Spline );
1194   }
1195   if ( update )
1196     myPlot->replot();
1197 }
1198 /*!
1199   Shows/hides legend
1200 */
1201 void Plot2d_ViewFrame::showLegend( bool show, bool update )
1202 {
1203   myShowLegend = show;
1204   myActions[ LegendId ]->setOn( myShowLegend );
1205   {
1206     myPlot->setAutoLegend( myShowLegend );
1207     myPlot->enableLegend( myShowLegend );
1208   }
1209   if ( update )
1210     myPlot->replot();
1211 }
1212 /*!
1213   Sets legend position : 0 - left, 1 - right, 2 - top, 3 - bottom
1214 */
1215 void Plot2d_ViewFrame::setLegendPos( int pos )
1216 {
1217   myLegendPos = pos;
1218   switch( pos ) {
1219   case 0:
1220     myPlot->setLegendPos( Qwt::Left );
1221     break;
1222   case 1:
1223     myPlot->setLegendPos( Qwt::Right );
1224     break;
1225   case 2:
1226     myPlot->setLegendPos( Qwt::Top );
1227     break;
1228   case 3:
1229     myPlot->setLegendPos( Qwt::Bottom );
1230     break;
1231   }
1232 }
1233 /*!
1234   Sets new marker size
1235 */
1236 void Plot2d_ViewFrame::setMarkerSize( const int size, bool update )
1237 {
1238   if ( myMarkerSize != size ) {
1239     myMarkerSize = size;
1240     QArray<long> keys = myPlot->curveKeys();
1241     for ( int i = 0; i < keys.count(); i++ ) {
1242       QwtPlotCurve* crv = myPlot->curve( keys[i] );
1243       if ( crv ) {
1244         QwtSymbol aSymbol = crv->symbol();
1245         aSymbol.setSize( myMarkerSize, myMarkerSize );
1246         crv->setSymbol( aSymbol );
1247         int legendIndex = myPlot->getLegend()->findFirstKey( keys[i] );
1248         if ( legendIndex != myPlot->getLegend()->itemCnt() )
1249           myPlot->getLegend()->setSymbol( legendIndex, aSymbol );
1250       }
1251     }
1252     if ( update )
1253       myPlot->replot();
1254   }
1255 }
1256 /*!
1257   Sets background color
1258 */
1259 void Plot2d_ViewFrame::setBackgroundColor( const QColor& color )
1260 {
1261   myBackground = color;
1262   //myPlot->setCanvasBackground( myBackground );
1263   myPlot->canvas()->setPalette( myBackground );
1264   myPlot->setPalette( myBackground );
1265   QPalette aPal = myPlot->getLegend()->palette();
1266   for ( int i = 0; i < QPalette::NColorGroups; i++ ) {
1267     QPalette::ColorGroup cg = (QPalette::ColorGroup)i;
1268     aPal.setColor( cg, QColorGroup::Base, myBackground );
1269     aPal.setColor( cg, QColorGroup::Background, myBackground );
1270   }
1271   myPlot->getLegend()->setPalette( aPal );
1272 }
1273 /*!
1274   Gets background color
1275 */
1276 QColor Plot2d_ViewFrame::backgroundColor() const
1277 {
1278   return myBackground;
1279 }
1280 /*!
1281   Sets hor.axis grid parameters
1282 */
1283 void Plot2d_ViewFrame::setXGrid( bool xMajorEnabled, const int xMajorMax, 
1284                                  bool xMinorEnabled, const int xMinorMax, 
1285                                  bool update )
1286 {
1287   myXGridMajorEnabled = xMajorEnabled;
1288   myXGridMinorEnabled = xMinorEnabled;
1289   myXGridMaxMajor = xMajorMax;
1290   myXGridMaxMinor = xMinorMax;
1291   myPlot->setAxisMaxMajor( QwtPlot::xBottom, myXGridMaxMajor );
1292   myPlot->setAxisMaxMinor( QwtPlot::xBottom, myXGridMaxMinor );
1293   myPlot->enableGridX( myXGridMajorEnabled );
1294   myPlot->enableGridXMin( myXGridMinorEnabled );
1295   if ( update )
1296     myPlot->replot();
1297 }
1298 /*!
1299   Sets ver.axis grid parameters
1300 */
1301 void Plot2d_ViewFrame::setYGrid( bool yMajorEnabled, const int yMajorMax, 
1302                                  bool yMinorEnabled, const int yMinorMax, 
1303                                  bool update )
1304 {
1305   myYGridMajorEnabled = yMajorEnabled;
1306   myYGridMinorEnabled = yMinorEnabled;
1307   myYGridMaxMajor = yMajorMax;
1308   myYGridMaxMinor = yMinorMax;
1309   myPlot->setAxisMaxMajor( QwtPlot::yLeft, myYGridMaxMajor );
1310   myPlot->setAxisMaxMinor( QwtPlot::yLeft, myYGridMaxMinor );
1311   myPlot->enableGridY( myYGridMajorEnabled );
1312   myPlot->enableGridYMin( myYGridMinorEnabled );
1313   if ( update )
1314     myPlot->replot();
1315 }
1316 /*!
1317   Sets main title
1318 */
1319 void Plot2d_ViewFrame::setMainTitle( bool enabled, const QString& title, bool update )
1320 {
1321   myTitleEnabled = enabled;
1322   myTitle = title;
1323   myPlot->setTitle( myTitleEnabled ? myTitle : QString::null );
1324   if ( update )
1325     myPlot->replot();
1326 }
1327 /*!
1328   Sets hor.axis title
1329 */
1330 void Plot2d_ViewFrame::setXTitle( bool enabled, const QString& title, bool update )
1331 {
1332   myXTitleEnabled = enabled;
1333   myXTitle = title;
1334   myPlot->setAxisTitle( QwtPlot::xBottom, myXTitleEnabled ? myXTitle : QString::null );
1335   if ( update )
1336     myPlot->replot();
1337 }
1338 /*!
1339   Sets ver.axis title
1340 */
1341 void Plot2d_ViewFrame::setYTitle( bool enabled, const QString& title, bool update )
1342 {
1343   myYTitleEnabled = enabled;
1344   myYTitle = title;
1345   myPlot->setAxisTitle( QwtPlot::yLeft, myYTitleEnabled ? myYTitle : QString::null );
1346   if ( update )
1347     myPlot->replot();
1348 }
1349 /*!
1350   Sets scale mode for horizontal axis: 0 - linear, 1 - logarithmic
1351 */
1352 void Plot2d_ViewFrame::setHorScaleMode( const int mode, bool update )
1353 {
1354   myXMode = mode;
1355   if ( myXMode == 0 ) { // linear
1356     myActions[ ModeXLogarithmicId ]->setOn( false );
1357     myActions[ ModeXLinearId ]->setOn( true );
1358     myPlot->changeAxisOptions( QwtPlot::xBottom, QwtAutoScale::Logarithmic, false );
1359   }
1360   else {               // logarithmic
1361     myActions[ ModeXLinearId ]->setOn( false );
1362     myActions[ ModeXLogarithmicId ]->setOn( true );
1363     myPlot->changeAxisOptions( QwtPlot::xBottom, QwtAutoScale::Logarithmic, true );
1364   }
1365   if ( update )
1366 //    myPlot->replot();
1367     fitAll();
1368 }
1369 /*!
1370   Sets scale mode for vertical axis: 0 - linear, 1 - logarithmic
1371 */
1372 void Plot2d_ViewFrame::setVerScaleMode( const int mode, bool update )
1373 {
1374   myYMode = mode;
1375   if ( myYMode == 0 ) { // linear
1376     myActions[ ModeYLogarithmicId ]->setOn( false );
1377     myActions[ ModeYLinearId ]->setOn( true );
1378     myPlot->changeAxisOptions( QwtPlot::yLeft, QwtAutoScale::Logarithmic, false );
1379   }
1380   else {               // logarithmic
1381     myActions[ ModeYLinearId ]->setOn( false );
1382     myActions[ ModeYLogarithmicId ]->setOn( true );
1383     myPlot->changeAxisOptions( QwtPlot::yLeft, QwtAutoScale::Logarithmic, true );
1384   }
1385   if ( update )
1386 //    myPlot->replot();
1387     fitAll();
1388 }
1389 /*!
1390   Slot, called when Legend item is clicked
1391 */
1392 void Plot2d_ViewFrame::onLegendClicked( long key )
1393 {
1394   Plot2d_Curve* curve = myCurves[ key ];
1395   if ( curve && curve->hasIO() ) {
1396     SALOME_Selection* Sel = SALOME_Selection::Selection( QAD_Application::getDesktop()->getActiveStudy()->getSelection() );
1397     Sel->ClearIObjects();
1398     Sel->AddIObject( curve->getIO(), true );
1399   }
1400 }
1401
1402 /*!
1403   Slot, called when user presses mouse button
1404 */
1405 void Plot2d_ViewFrame::plotMousePressed( const QMouseEvent& me )
1406 {
1407   if ( myOperation == NoOpId )
1408     myOperation = testOperation( me );
1409   if ( myOperation != NoOpId ) {
1410     myPnt = me.pos();
1411     if ( myOperation == ZoomId ) {
1412       myPlot->canvas()->setCursor( QCursor( QPixmap( imageZoomCursor ) ) );
1413     }
1414     else if ( myOperation == PanId ) {
1415       myPlot->canvas()->setCursor( QCursor( Qt::SizeAllCursor ) );
1416     }
1417     else if ( myOperation == FitAreaId ) {
1418       myPlot->canvas()->setCursor( QCursor( Qt::PointingHandCursor ) );
1419       myPlot->setOutlineStyle( Qwt::Rect );
1420     }
1421   }
1422   else {
1423     int btn = me.button() | me.state();
1424     if ( btn == RightButton ) {
1425       createPopup();
1426       if ( myPopup ) {
1427         QAD_Tools::checkPopup( myPopup );
1428         if ( myPopup->count()>0 ) {
1429           myPopup->exec( QCursor::pos() );
1430         }
1431         destroyPopup();
1432       }
1433     }
1434     else {
1435       myPlot->setOutlineStyle( Qwt::Cross );
1436       QAD_Application::getDesktop()->putInfo( getInfo( me.pos() ) );
1437     }
1438   }
1439 }
1440 /*!
1441   Slot, called when user moves mouse
1442 */
1443 void Plot2d_ViewFrame::plotMouseMoved( const QMouseEvent& me )
1444 {
1445   int    dx = me.pos().x() - myPnt.x();
1446   int    dy = me.pos().y() - myPnt.y();
1447
1448   if ( myOperation != NoOpId) {
1449     if ( myOperation == ZoomId ) {
1450       this->incrementalZoom( dx, dy ); 
1451       myPnt = me.pos();
1452     }
1453     else if ( myOperation == PanId ) {
1454       this->incrementalPan( dx, dy );
1455       myPnt = me.pos();
1456     }
1457   }
1458   else {
1459     QAD_Application::getDesktop()->putInfo( getInfo( me.pos() ) );
1460   }
1461 }
1462 /*!
1463   Slot, called when user releases mouse
1464 */
1465 void Plot2d_ViewFrame::plotMouseReleased( const QMouseEvent& me )
1466 {
1467   if ( myOperation == FitAreaId ) {
1468     QRect rect( myPnt, me.pos() );
1469     fitArea( rect );
1470   }
1471   myPlot->canvas()->setCursor( QCursor( Qt::CrossCursor ) );
1472   myPlot->setOutlineStyle( Qwt::Triangle );
1473   QAD_Application::getDesktop()->putInfo( tr( "INF_READY" ) );
1474   myOperation = NoOpId;
1475 }
1476 /*!
1477   View operations : Pan view
1478 */
1479 void Plot2d_ViewFrame::onViewPan() 
1480
1481   myOperation = PanId;
1482   qApp->installEventFilter( this );
1483 }
1484 /*!
1485   View operations : Zoom view
1486 */
1487 void Plot2d_ViewFrame::onViewZoom() 
1488 {
1489   myOperation = ZoomId;
1490   qApp->installEventFilter( this );
1491 }
1492 /*!
1493   View operations : Fot All
1494 */
1495 void Plot2d_ViewFrame::onViewFitAll() 
1496
1497   fitAll();
1498 }
1499 /*!
1500   View operations : Fit Area
1501 */
1502 void Plot2d_ViewFrame::onViewFitArea() 
1503 {
1504   myOperation = FitAreaId;
1505   qApp->installEventFilter( this );
1506 }
1507 /*!
1508   View operations : Global panning
1509 */
1510 void Plot2d_ViewFrame::onViewGlobalPan() 
1511 { MESSAGE( "Plot2d_ViewFrame::onViewGlobalPan : NOT SUPPORTED" ); }
1512 /*!
1513   View operations : Rotate view
1514 */
1515 void Plot2d_ViewFrame::onViewRotate() 
1516 { MESSAGE( "Plot2d_ViewFrame::onViewRotate : NOT SUPPORTED" ); }
1517 /*!
1518   View operations : Reset view
1519 */
1520 void Plot2d_ViewFrame::onViewReset() 
1521 { MESSAGE( "Plot2d_ViewFrame::onViewReset : NOT SUPPORTED" ); }
1522 /*!
1523   View operations : View front
1524 */
1525 void Plot2d_ViewFrame::onViewFront() 
1526 { MESSAGE( "Plot2d_ViewFrame::onViewFront : NOT SUPPORTED" ); }
1527 /*!
1528   View operations : View back
1529 */
1530 void Plot2d_ViewFrame::onViewBack() 
1531 { MESSAGE( "Plot2d_ViewFrame::onViewBack : NOT SUPPORTED" ); }
1532 /*!
1533   View operations : View right
1534 */
1535 void Plot2d_ViewFrame::onViewRight() 
1536 { MESSAGE( "Plot2d_ViewFrame::onViewRight : NOT SUPPORTED" ); }
1537 /*!
1538   View operations : View left
1539 */
1540 void Plot2d_ViewFrame::onViewLeft() 
1541 { MESSAGE( "Plot2d_ViewFrame::onViewLeft : NOT SUPPORTED" ); }
1542 /*!
1543   View operations : View bottom
1544 */
1545 void Plot2d_ViewFrame::onViewBottom() 
1546 { MESSAGE( "Plot2d_ViewFrame::onViewBottom : NOT SUPPORTED" ); }
1547 /*!
1548   View operations : View top
1549 */
1550 void Plot2d_ViewFrame::onViewTop() 
1551 { MESSAGE( "Plot2d_ViewFrame::onViewTop : NOT SUPPORTED" ); }
1552 /*!
1553   View operations : Show/hide trihedron
1554 */
1555 void Plot2d_ViewFrame::onViewTrihedron() 
1556 { MESSAGE( "Plot2d_ViewFrame::onViewTrihedron : NOT SUPPORTED" ); }
1557
1558
1559 //=================================================================================
1560 // Plot2d_Plot2d implementation
1561 //=================================================================================
1562
1563 /*!
1564   Constructor
1565 */
1566 Plot2d_Plot2d::Plot2d_Plot2d( QWidget* parent )
1567      : QwtPlot( parent )
1568 {
1569   // outline
1570   enableOutline( true );
1571   setOutlineStyle( Qwt::Triangle );
1572   setOutlinePen( green );
1573   // legend
1574   setAutoLegend( false );
1575   setLegendFrameStyle( QFrame::Box | QFrame::Sunken );
1576   enableLegend( false );
1577   // grid
1578   enableGridX( false );
1579   enableGridXMin( false );
1580   enableGridY( false );
1581   enableGridYMin( false );
1582   // auto scaling by default
1583   setAxisAutoScale( QwtPlot::yLeft );
1584   setAxisAutoScale( QwtPlot::xBottom );
1585 }
1586 /*!
1587   Recalculates and redraws Plot 2d view 
1588 */
1589 void Plot2d_Plot2d::replot()
1590 {
1591   updateLayout();  // to fix bug(?) of Qwt - view is not updated when title is changed
1592   QwtPlot::replot(); 
1593 }
1594 /*!
1595   Checks if two colors are close to each other [ static ]
1596   uses COLOR_DISTANCE variable as max tolerance for comparing of colors
1597 */
1598 const long COLOR_DISTANCE = 100;
1599 const int  MAX_ATTEMPTS   = 10;
1600 static bool closeColors( const QColor& color1, const QColor& color2 )
1601 {
1602   long tol = abs( color2.red()   - color1.red() ) + 
1603              abs( color2.green() - color1.green() ) +
1604              abs( color2.blue()  - color1.blue() );
1605
1606   return ( tol <= COLOR_DISTANCE );
1607 }
1608 /*!
1609   Gets new unique marker for item if possible
1610 */
1611 void Plot2d_Plot2d::getNextMarker( QwtSymbol::Style& typeMarker, QColor& color, Qt::PenStyle& typeLine ) 
1612 {
1613   bool bOk = false;
1614   int cnt = 1;
1615   while ( !bOk ) {
1616     int aRed    = (int)( 256.0 * random() / RAND_MAX);    // generate random color
1617     int aGreen  = (int)( 256.0 * random() / RAND_MAX);    // ...
1618     int aBlue   = (int)( 256.0 * random() / RAND_MAX);    // ...
1619     int aMarker = (int)( 9.0 * random() / RAND_MAX) + 1;  // 9 markers types ( not including empty )
1620     int aLine   = (int)( 5.0 * random() / RAND_MAX) + 1;  // 5 line types ( not including empty )
1621
1622     typeMarker = ( QwtSymbol::Style )aMarker;
1623     color      = QColor( aRed, aGreen, aBlue );
1624     typeLine   = ( Qt::PenStyle )aLine;
1625
1626     cnt++;
1627     if ( cnt == MAX_ATTEMPTS )
1628       bOk = true;
1629     else
1630       bOk = !existMarker( typeMarker, color, typeLine );
1631   }
1632 /*
1633   static int aMarker = -1;
1634   static int aColor  = -1;
1635   static int aLine   = -1;
1636
1637   if ( myColors.isEmpty() ) {
1638     // creating colors list
1639     myColors.append( Qt::white );
1640     myColors.append( Qt::blue );
1641     myColors.append( Qt::gray );
1642     myColors.append( Qt::darkGreen );
1643     myColors.append( Qt::magenta );
1644     myColors.append( Qt::darkGray );
1645     myColors.append( Qt::red );
1646     myColors.append( Qt::darkBlue );
1647     myColors.append( Qt::darkYellow );
1648     myColors.append( Qt::cyan );
1649     myColors.append( Qt::darkRed );
1650     myColors.append( Qt::darkCyan );
1651     myColors.append( Qt::yellow );
1652     myColors.append( Qt::darkMagenta );
1653     myColors.append( Qt::green );
1654     myColors.append( Qt::black );
1655   }
1656
1657   int nbMarkers = 11;                   // QwtSymbol supports 11 marker types
1658   int nbLines   = 6;                    // Qt supports 6 line types
1659   int nbColors  = myColors.count();     // number of default colors supported
1660
1661   aMarker = ( aMarker + 1 ) % nbMarkers;  
1662   if ( aMarker == QwtSymbol::None || aMarker == QwtSymbol::Triangle ) aMarker++;
1663   aColor  = ( aColor  + 1 ) % nbColors;
1664   aLine   = ( aLine   + 1 ) % nbLines;    
1665   if ( aLine == Qt::NoPen ) aLine++;             
1666
1667   typeMarker = ( QwtSymbol::Style )aMarker;
1668   color      = myColors[ aColor ];
1669   typeLine   = ( Qt::PenStyle )aLine;
1670   if ( !existMarker( typeMarker, color, typeLine ) )
1671     return;
1672
1673   int i, j, k;
1674   for ( i = 0; i < nbMarkers; i++ ) {
1675     aMarker = ( aMarker + 1 ) % nbMarkers;
1676     if ( aMarker == QwtSymbol::None || aMarker == QwtSymbol::Triangle ) aMarker++;
1677     for ( j = 0; j < nbColors; j++ ) {
1678       aColor  = ( aColor  + 1 ) % nbColors;
1679       for ( k = 0; k < nbLines; k++ ) {
1680         aLine = ( aLine + 1 ) % nbLines;
1681         if ( aLine == Qt::NoPen ) aLine++;             
1682         if ( !existMarker( ( QwtSymbol::Style )aMarker, aColor, ( Qt::PenStyle )aLine ) ) {
1683           typeMarker = ( QwtSymbol::Style )aMarker;
1684           color      = myColors[ aColor ];
1685           typeLine   = ( Qt::PenStyle )aLine;
1686           return;
1687         }
1688       }
1689     }
1690   }
1691 */
1692 }
1693 /*!
1694   Checks if marker belongs to any enitity
1695 */
1696 bool Plot2d_Plot2d::existMarker( const QwtSymbol::Style typeMarker, const QColor& color, const Qt::PenStyle typeLine ) 
1697 {
1698   // getting all curves
1699   QArray<long> keys = curveKeys();
1700   QColor aRgbColor;
1701
1702   if ( closeColors( color, backgroundColor() ) )
1703       return true;
1704   for ( int i = 0; i < keys.count(); i++ ) {
1705     QwtPlotCurve* crv = curve( keys[i] );
1706     if ( crv ) {
1707       QwtSymbol::Style aStyle = crv->symbol().style();
1708       QColor           aColor = crv->pen().color();
1709       Qt::PenStyle     aLine  = crv->pen().style();
1710 //      if ( aStyle == typeMarker && aColor == color && aLine == typeLine )
1711       if ( aStyle == typeMarker && closeColors( aColor,color ) && aLine == typeLine )
1712         return true;
1713     }
1714   }
1715   return false;
1716 }
1717
1718 //==========================================================
1719 /*!
1720  *  Plot2d_ViewFrame::Display
1721  *  Display presentation
1722  */
1723 //==========================================================
1724 void Plot2d_ViewFrame::Display( const SALOME_Prs2d* prs )
1725 {
1726   // try do downcast object
1727   const Plot2d_Prs* aPlot2dPrs = dynamic_cast<const Plot2d_Prs*>( prs );
1728   if ( !aPlot2dPrs || aPlot2dPrs->IsNull() )
1729     return;
1730
1731   // display all curves from presentation
1732   Plot2d_CurveContainer aCurves = aPlot2dPrs->GetObjects();
1733   displayCurves( aCurves );
1734 }
1735
1736 //==========================================================
1737 /*!
1738  *  Plot2d_ViewFrame::Erase
1739  *  Erase presentation
1740  */
1741 //==========================================================
1742 void Plot2d_ViewFrame::Erase( const SALOME_Prs2d* prs, const bool )
1743 {
1744   // try do downcast object
1745   const Plot2d_Prs* aPlot2dPrs = dynamic_cast<const Plot2d_Prs*>( prs );
1746   if ( !aPlot2dPrs || aPlot2dPrs->IsNull() )
1747     return;
1748
1749   // erase all curves from presentation
1750   Plot2d_CurveContainer aCurves = aPlot2dPrs->GetObjects();
1751   eraseCurves( aCurves );
1752 }
1753   
1754 //==========================================================
1755 /*!
1756  *  Plot2d_ViewFrame::CreatePrs
1757  *  Create presentation by entry
1758  */
1759 //==========================================================
1760 SALOME_Prs* Plot2d_ViewFrame::CreatePrs( const char* entry )
1761 {
1762   Plot2d_Prs* prs = new Plot2d_Prs();
1763   if ( entry ) {
1764     QIntDictIterator<Plot2d_Curve> it( myCurves );
1765     for ( ; it.current(); ++it ) {
1766       if ( it.current()->hasIO() && !strcmp( it.current()->getIO()->getEntry(), entry ) ) {
1767         prs->AddObject( it.current() );
1768       }
1769     }
1770   }
1771   return prs;
1772 }
1773
1774 //==========================================================
1775 /*!
1776  *  Plot2d_ViewFrame::BeforeDisplay
1777  *  Axiluary method called before displaying of objects
1778  */
1779 //==========================================================
1780 void  Plot2d_ViewFrame::BeforeDisplay( SALOME_Displayer* d )
1781 {
1782   d->BeforeDisplay( this, SALOME_Plot2dViewType() );
1783 }
1784
1785 //==========================================================
1786 /*!
1787  *  Plot2d_ViewFrame::AfterDisplay
1788  *  Axiluary method called after displaying of objects
1789  */
1790 //==========================================================
1791 void  Plot2d_ViewFrame::AfterDisplay( SALOME_Displayer* d )
1792 {
1793   d->AfterDisplay( this, SALOME_Plot2dViewType() );
1794 }
1795
1796 #define INCREMENT_FOR_OP 10
1797
1798 //=======================================================================
1799 // Plot2d_ViewFrame::onPanLeft
1800 // Performs incremental panning to the left
1801 //=======================================================================
1802 void Plot2d_ViewFrame::onPanLeft()
1803 {
1804   this->incrementalPan( -INCREMENT_FOR_OP, 0 );
1805 }
1806
1807 //=======================================================================
1808 // Plot2d_ViewFrame::onPanRight
1809 // Performs incremental panning to the right
1810 //=======================================================================
1811 void Plot2d_ViewFrame::onPanRight()
1812 {
1813   this->incrementalPan( INCREMENT_FOR_OP, 0 );
1814 }
1815
1816 //=======================================================================
1817 // Plot2d_ViewFrame::onPanUp
1818 // Performs incremental panning to the top
1819 //=======================================================================
1820 void Plot2d_ViewFrame::onPanUp()
1821 {
1822   this->incrementalPan( 0, -INCREMENT_FOR_OP );
1823 }
1824
1825 //=======================================================================
1826 // Plot2d_ViewFrame::onPanDown
1827 // Performs incremental panning to the bottom
1828 //=======================================================================
1829 void Plot2d_ViewFrame::onPanDown()
1830 {
1831   this->incrementalPan( 0, INCREMENT_FOR_OP );
1832 }
1833
1834 //=======================================================================
1835 // Plot2d_ViewFrame::onZoomIn
1836 // Performs incremental zooming in
1837 //=======================================================================
1838 void Plot2d_ViewFrame::onZoomIn()
1839 {
1840   this->incrementalZoom( INCREMENT_FOR_OP, INCREMENT_FOR_OP );
1841 }
1842
1843 //=======================================================================
1844 // Plot2d_ViewFrame::onZoomOut
1845 // Performs incremental zooming out
1846 //=======================================================================
1847 void Plot2d_ViewFrame::onZoomOut()
1848 {
1849   this->incrementalZoom( -INCREMENT_FOR_OP, -INCREMENT_FOR_OP );
1850 }
1851
1852 //=======================================================================
1853 // Plot2d_ViewFrame::incrementalPan
1854 // Incremental zooming operation
1855 //=======================================================================
1856 void Plot2d_ViewFrame::incrementalPan( const int incrX, const int incrY ) {
1857   QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
1858   QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
1859   
1860   myPlot->setAxisScale( QwtPlot::yLeft,
1861                         myPlot->invTransform( QwtPlot::yLeft, yMap.i1()-incrY ),
1862                         myPlot->invTransform( QwtPlot::yLeft, yMap.i2()-incrY ) );
1863   myPlot->setAxisScale( QwtPlot::xBottom,
1864                         myPlot->invTransform( QwtPlot::xBottom, xMap.i1()-incrX ),
1865                         myPlot->invTransform( QwtPlot::xBottom, xMap.i2()-incrX ) );
1866   myPlot->replot();
1867 }
1868
1869 //=======================================================================
1870 // Plot2d_ViewFrame::incrementalZoom
1871 // Incremental panning operation
1872 //=======================================================================
1873 void Plot2d_ViewFrame::incrementalZoom( const int incrX, const int incrY ) {
1874   QwtDiMap xMap = myPlot->canvasMap( QwtPlot::xBottom );
1875   QwtDiMap yMap = myPlot->canvasMap( QwtPlot::yLeft );
1876   
1877   myPlot->setAxisScale( QwtPlot::yLeft,
1878                        myPlot->invTransform( QwtPlot::yLeft, yMap.i1() ),
1879                        myPlot->invTransform( QwtPlot::yLeft, yMap.i2() + incrY ) );
1880   myPlot->setAxisScale( QwtPlot::xBottom,
1881                        myPlot->invTransform( QwtPlot::xBottom, xMap.i1() ),
1882                        myPlot->invTransform( QwtPlot::xBottom, xMap.i2() - incrX ) );
1883   myPlot->replot();
1884 }
1885