Salome HOME
Porting python light modules to WIN32 platform.
[modules/gui.git] / src / OCCViewer / OCCViewer_ViewFrame.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include "OCCViewer_ViewFrame.h"
24 #include "OCCViewer_ViewWindow.h"
25 #include "OCCViewer_ViewModel.h"
26
27 #include <SUIT_ViewManager.h>
28 #include <SUIT_Session.h>
29 #include <SUIT_ResourceMgr.h>
30
31 #include <QtxResourceMgr.h>
32 #include <QtxWorkstackAction.h>
33
34 #include <QFrame>
35 #include <QLayout>
36 #include <QApplication>
37
38 OCCViewer_ViewFrame::OCCViewer_ViewFrame(SUIT_Desktop* theDesktop, OCCViewer_Viewer* theModel)
39   : OCCViewer_ViewWindow( theDesktop, theModel ), myPopupRequestedView(0), mySplitMode(-1)
40 {
41   QFrame* centralFrame = new QFrame( this );
42   setCentralWidget( centralFrame );
43
44   OCCViewer_ViewWindow* view0 = theModel->createSubWindow();
45   updateWindowTitle( view0 );
46   view0->setParent( centralFrame );
47   myViews.append( view0 ); // MAIN_VIEW
48
49   myLayout = new QGridLayout( centralFrame );
50   myLayout->setMargin( 0 );
51   myLayout->setSpacing( 1 );
52
53   myLayout->addWidget( view0, 0, 0 );
54   myMaximizedView = view0;
55   connectViewSignals(view0);
56 }
57
58 OCCViewer_ViewFrame::~OCCViewer_ViewFrame()
59 {
60 }
61
62 bool OCCViewer_ViewFrame::event( QEvent* e )
63 {
64   if ( e->type() == QEvent::WindowTitleChange ) {
65     updateWindowTitle( getView( MAIN_VIEW ) );
66     updateWindowTitle( getView( BOTTOM_LEFT ) );
67     updateWindowTitle( getView( TOP_LEFT ) );
68     updateWindowTitle( getView( TOP_RIGHT ) );
69   }
70   return OCCViewer_ViewWindow::event( e );
71 }
72
73 //**************************************************************************************
74 OCCViewer_ViewWindow* OCCViewer_ViewFrame::getView( const int i ) const
75 {
76   return ( i >= 0 && i < myViews.count() ) ? myViews.at( i ) : 0 ;
77 }
78
79 //**************************************************************************************
80 void OCCViewer_ViewFrame::setViewManager( SUIT_ViewManager* theMgr )
81 {
82   OCCViewer_ViewWindow::setViewManager(theMgr);
83   foreach (OCCViewer_ViewWindow* aView, myViews) {
84     aView->setViewManager(theMgr); 
85   }
86 }
87
88 //**************************************************************************************
89 void OCCViewer_ViewFrame::onMaximizedView( OCCViewer_ViewWindow* theView, bool isMaximized)
90 {
91   myMaximizedView = theView;
92   if (isMaximized) {
93     if (myViews.count() <= 1)
94       return;
95     myLayout->setColumnStretch(0, 0);
96     myLayout->setColumnStretch(1, 0);
97     myLayout->addWidget( theView, 0, 0 );
98     int i = 0;
99     OCCViewer_ViewWindow* view = 0;
100     for ( i = BOTTOM_RIGHT; i <= TOP_RIGHT; i++ ) {
101       view = myViews.at(i);
102       view->setVisible( view == theView );
103       view->setMaximized( view == theView, false );
104     }
105     mySplitMode = -1;
106     myViewsMode.clear();
107   }
108   else {
109     createSubViews();
110
111     QtxSplitDlg CreateSubViewsDlg( this, NULL, CreateSubViews );
112     if ( CreateSubViewsDlg.exec() ) {
113       mySplitMode = CreateSubViewsDlg.getSplitMode();
114       myViewsMode = CreateSubViewsDlg.getViewsMode();
115       splitSubViews();
116     }
117     else {
118       myMaximizedView->setMaximized(true);
119     }
120   }
121   myLayout->invalidate();
122 }
123
124 //**************************************************************************************
125 void OCCViewer_ViewFrame::createSubViews()
126 {
127   OCCViewer_Viewer* aModel = dynamic_cast<OCCViewer_Viewer*>(myManager->getViewModel());
128   if (!aModel) return;
129   int i = 0;
130   if (myViews.count() == 1) {
131     //QColor aColor = myViews.at( MAIN_VIEW )->backgroundColor();
132     OCCViewer_ViewWindow* view = 0;
133     for ( i = BOTTOM_LEFT; i <= TOP_RIGHT; i++) {
134       view = aModel->createSubWindow();
135       view->set2dMode( (Mode2dType) i );
136       view->setParent( centralWidget() );
137       view->setViewManager(myManager);
138       updateWindowTitle( view );
139       myViews.append( view );
140       aModel->initView(view);
141       view->setMaximized(false, false);
142       view->setDropDownButtons( dropDownButtons() );
143       connectViewSignals(view);
144       view->setBackground(aModel->background(i));
145     }
146   }
147 }
148
149 void OCCViewer_ViewFrame::splitSubViews()
150 {
151         if( mySplitMode == -1 )
152                 return;
153
154   int aNbViews;
155   if ( mySplitMode >= 0 && mySplitMode < 2)
156     aNbViews = 2;
157   else if( mySplitMode >= 2 && mySplitMode < 8 )
158     aNbViews = 3;
159   else if( mySplitMode >=8 && mySplitMode < 29 )
160     aNbViews = 4;
161
162   if( aNbViews != myViewsMode.count() )
163         return;
164
165   int SubViews3Map[6][3][4] = {
166     { {0,0,1,1}, {0,1,1,1}, {0,2,1,1} },
167     { {0,0,1,1}, {1,0,1,1}, {2,0,1,1} },
168     { {0,0,1,1}, {1,0,1,1}, {0,1,2,1} },
169     { {0,0,2,1}, {0,1,1,1}, {1,1,1,1} },
170     { {0,0,1,2}, {1,0,1,1}, {1,1,1,1} },
171     { {0,0,1,1}, {0,1,1,1}, {1,0,1,2} }
172   };
173
174   int SubViews4Map[21][4][4] = {
175     { {0,0,1,1}, {0,1,1,1}, {0,2,1,1}, {0,3,1,1} },
176     { {0,0,1,1}, {1,0,1,1}, {2,0,1,1}, {3,0,1,1} },
177     { {0,0,1,1}, {0,1,1,1}, {1,0,1,1}, {1,1,1,1} },
178     { {0,0,1,1}, {1,0,1,1}, {0,1,2,1}, {0,2,2,1} },
179     { {0,0,2,1}, {0,1,1,1}, {1,1,1,1}, {0,2,2,1} },
180     { {0,0,2,1}, {0,1,2,1}, {0,2,1,1}, {1,2,1,1} },
181     { {0,0,1,1}, {0,1,1,1}, {1,0,1,2}, {2,0,1,2} },
182     { {0,0,1,2}, {1,0,1,1}, {1,1,1,1}, {2,0,1,2} },
183     { {0,0,1,2}, {1,0,1,2}, {2,0,1,1}, {2,1,1,1} },
184     { {0,0,1,1}, {1,0,1,1}, {0,1,2,1}, {2,0,1,2} },
185     { {0,0,2,1}, {0,1,1,1}, {1,1,1,1}, {2,0,1,2} },
186     { {0,0,1,2}, {1,0,1,1}, {2,0,1,1}, {1,1,2,1} },
187     { {0,0,1,2}, {1,0,2,1}, {1,1,1,1}, {2,1,1,1} },
188     { {0,0,2,1}, {0,1,1,1}, {0,2,1,1}, {1,1,1,2} },
189     { {0,0,2,1}, {0,1,1,2}, {1,1,1,1}, {1,2,1,1} },
190     { {0,0,1,1}, {0,1,1,1}, {1,0,1,2}, {0,2,2,1} },
191     { {0,0,1,2}, {1,0,1,1}, {1,1,1,1}, {0,2,2,1} },
192     { {0,0,1,3}, {1,0,1,1}, {1,1,1,1}, {1,2,1,1} },
193     { {0,0,1,1}, {0,1,1,1}, {0,2,1,1}, {1,0,1,3} },
194     { {0,0,1,1}, {1,0,1,1}, {2,0,1,1}, {0,1,3,1} },
195     { {0,0,3,1}, {0,1,1,1}, {1,1,1,1}, {2,1,1,1} },
196   };
197
198   if( aNbViews == 2 ) {
199     if( mySplitMode == 0 ) {
200       myLayout->addWidget( myViews.at(myViewsMode[0]), 0,0,2,1 );
201       myLayout->addWidget( myViews.at(myViewsMode[1]), 0,1,2,1 );
202     }
203     else if( mySplitMode == 1 ) {
204       myLayout->addWidget( myViews.at(myViewsMode[0]), 0,0,1,2 );
205       myLayout->addWidget( myViews.at(myViewsMode[1]), 1,0,1,2 );
206     }
207   }
208   else if( aNbViews == 3 ) {
209         int aSplitMode = mySplitMode - 2;
210     for( int i = 0; i < 3; i++ ) {
211     myLayout->addWidget( myViews.at(myViewsMode[i]),
212                          SubViews3Map[aSplitMode][i][0],
213                          SubViews3Map[aSplitMode][i][1],
214                          SubViews3Map[aSplitMode][i][2],
215                          SubViews3Map[aSplitMode][i][3]);
216     }
217   }
218   else if( aNbViews == 4 ) {
219         int aSplitMode = mySplitMode - 8;
220     for( int i = 0; i < 4; i++ ) {
221     myLayout->addWidget( myViews.at(myViewsMode[i]),
222                          SubViews4Map[aSplitMode][i][0],
223                          SubViews4Map[aSplitMode][i][1],
224                          SubViews4Map[aSplitMode][i][2],
225                          SubViews4Map[aSplitMode][i][3]);
226     }
227   }
228
229   OCCViewer_ViewWindow* view = 0;
230   for ( int i = 0; i< myViews.count(); i++ ) {
231     view = myViews.at(i);
232     bool isShowed = false;
233     for( int j = 0; j < myViewsMode.count(); j++ ) {
234       OCCViewer_ViewWindow* view2 = 0;
235       view2 = myViews.at( myViewsMode[j] );
236       if( view == view2 )
237         isShowed = true;
238     }
239     if( isShowed ) {
240       view->show();
241       view->setMaximized( false, false );
242       ///////////////QApplication::processEvents(); // VSR: hangs up ?
243       if ( view != myMaximizedView )
244         view->onViewFitAll();
245     }
246     else
247       view->setVisible( false );
248   }
249 }
250
251 //**************************************************************************************
252 OCCViewer_ViewPort3d* OCCViewer_ViewFrame::getViewPort(int theView) 
253
254   return getView(theView)? getView(theView)->getViewPort() : 0;
255 }
256   
257 //**************************************************************************************
258 void OCCViewer_ViewFrame::updateEnabledDrawMode() 
259
260   foreach (OCCViewer_ViewWindow* aView, myViews) {
261     aView->updateEnabledDrawMode(); 
262   }
263 }
264
265 //**************************************************************************************
266 void OCCViewer_ViewFrame::setCuttingPlane( bool on, const double x , const double y , const double z,
267                                            const double dx, const double dy, const double dz)  
268
269   foreach (OCCViewer_ViewWindow* aView, myViews) {
270     aView->setCuttingPlane(on, x, y, z, dx, dy, dz); 
271     aView->update();
272   }
273 }
274
275 //**************************************************************************************
276 void OCCViewer_ViewFrame::setCuttingPlane( bool on, const gp_Pln thePln ) 
277
278   foreach (OCCViewer_ViewWindow* aView, myViews) {
279     aView->setCuttingPlane(on, thePln); 
280     aView->update();
281   }
282 }
283   
284 //**************************************************************************************
285 void OCCViewer_ViewFrame::setInteractionStyle( const int i ) 
286
287   foreach (OCCViewer_ViewWindow* aView, myViews) {
288     aView->setInteractionStyle(i); 
289   }
290 }
291
292 //**************************************************************************************
293 void OCCViewer_ViewFrame::setZoomingStyle( const int i ) 
294
295   foreach (OCCViewer_ViewWindow* aView, myViews) {
296     aView->setZoomingStyle(i); 
297   }
298 }
299   
300 //**************************************************************************************
301 void OCCViewer_ViewFrame::connectViewSignals(OCCViewer_ViewWindow* theView)
302 {
303   connect( theView, SIGNAL( maximized( OCCViewer_ViewWindow*, bool ) ), 
304            this, SLOT( onMaximizedView( OCCViewer_ViewWindow*, bool ) ) );
305
306   connect( theView, SIGNAL( wheeling(SUIT_ViewWindow*, QWheelEvent*) ), 
307            this, SIGNAL( wheeling(SUIT_ViewWindow*, QWheelEvent*) ) );
308
309   connect( theView, SIGNAL( keyReleased(SUIT_ViewWindow*, QKeyEvent*) ), 
310            this, SIGNAL( keyReleased(SUIT_ViewWindow*, QKeyEvent*) ) );
311   connect( theView, SIGNAL( keyPressed(SUIT_ViewWindow*, QKeyEvent*) ), 
312            this, SIGNAL( keyPressed(SUIT_ViewWindow*, QKeyEvent*) ) );
313
314   connect( theView, SIGNAL( mouseDoubleClicked(SUIT_ViewWindow*, QMouseEvent*) ), 
315            this, SIGNAL( mouseDoubleClicked(SUIT_ViewWindow*, QMouseEvent*) ) );
316   connect( theView, SIGNAL( mousePressed(SUIT_ViewWindow*, QMouseEvent*) ), 
317            this, SIGNAL( mousePressed(SUIT_ViewWindow*, QMouseEvent*) ) );
318   connect( theView, SIGNAL( mouseReleased(SUIT_ViewWindow*, QMouseEvent*) ), 
319            this, SIGNAL( mouseReleased(SUIT_ViewWindow*, QMouseEvent*) ) );
320   connect( theView, SIGNAL( mouseMoving(SUIT_ViewWindow*, QMouseEvent*) ), 
321            this, SIGNAL( mouseMoving(SUIT_ViewWindow*, QMouseEvent*) ) );
322
323   // The signal is used to process get/set background color from popup
324   connect( theView, SIGNAL( contextMenuRequested(QContextMenuEvent*) ), 
325            this, SLOT( onContextMenuRequested(QContextMenuEvent*) ) );
326
327   connect( theView, SIGNAL( contextMenuRequested(QContextMenuEvent*) ), 
328            this, SIGNAL( contextMenuRequested(QContextMenuEvent*) ) );
329
330   connect( theView, SIGNAL( viewCloned( SUIT_ViewWindow* ) ),
331            this,    SIGNAL( viewCloned( SUIT_ViewWindow* ) ) );
332 }
333
334 // obsolete
335 void OCCViewer_ViewFrame::setBackgroundColor( const QColor& theColor )
336 {
337   if (myPopupRequestedView)
338     myPopupRequestedView->setBackgroundColor(theColor); 
339   else {
340     foreach (OCCViewer_ViewWindow* aView, myViews) {
341       if (aView->isVisible())
342         aView->setBackgroundColor(theColor); 
343     }
344   }
345 }
346 void OCCViewer_ViewFrame::setBackground( const Qtx::BackgroundData& theBackground )
347 {
348   if (myPopupRequestedView)
349     myPopupRequestedView->setBackground(theBackground); 
350   else {
351     foreach (OCCViewer_ViewWindow* aView, myViews) {
352       if (aView->isVisible())
353         aView->setBackground(theBackground); 
354     }
355   }
356 }
357
358 void OCCViewer_ViewFrame::onViewFitAll()
359 {
360   foreach (OCCViewer_ViewWindow* aView, myViews) {
361     aView->onViewFitAll(); 
362   }
363 }
364
365 void OCCViewer_ViewFrame::onFitAll()
366 {
367   foreach (OCCViewer_ViewWindow* aView, myViews) {
368     aView->onFitAll(); 
369   }
370 }
371
372 // obsolete  
373 QColor OCCViewer_ViewFrame::backgroundColor() const 
374
375   if (myPopupRequestedView)
376     return myPopupRequestedView->backgroundColor(); 
377
378   foreach (OCCViewer_ViewWindow* aView, myViews) {
379     if (aView->isVisible())
380       return aView->backgroundColor(); 
381   }
382   return getView(MAIN_VIEW)->backgroundColor(); 
383 }
384
385 Qtx::BackgroundData OCCViewer_ViewFrame::background() const 
386
387   if (myPopupRequestedView)
388     return myPopupRequestedView->background(); 
389
390   foreach (OCCViewer_ViewWindow* aView, myViews) {
391     if (aView->isVisible())
392       return aView->background(); 
393   }
394   return getView(MAIN_VIEW)->background(); 
395 }
396
397 QImage OCCViewer_ViewFrame::dumpView()
398 {
399   foreach (OCCViewer_ViewWindow* aView, myViews) {
400     if (aView->isVisible())
401       return aView->dumpView();
402   }
403   return QImage();
404 }
405
406 bool OCCViewer_ViewFrame::dumpViewToFormat( const QImage& image, const QString& fileName, const QString& format )
407 {
408   foreach (OCCViewer_ViewWindow* aView, myViews) {
409     if (aView->isVisible())
410       return aView->dumpViewToFormat( image, fileName, format );
411   }
412   return false;
413 }
414
415 void OCCViewer_ViewFrame::onContextMenuRequested(QContextMenuEvent*)
416 {
417   myPopupRequestedView = dynamic_cast<OCCViewer_ViewWindow*>(sender());
418 }
419
420 void OCCViewer_ViewFrame::onDumpView()
421 {
422   if (myPopupRequestedView) {
423     myPopupRequestedView->onDumpView(); 
424   }
425   else {
426     getView(MAIN_VIEW)->onDumpView(); 
427   }
428 }
429
430 void OCCViewer_ViewFrame::setDropDownButtons( bool on )
431 {
432   foreach( OCCViewer_ViewWindow* aView, myViews ) {
433     aView->setDropDownButtons( on );
434   }
435   OCCViewer_ViewWindow::setDropDownButtons( on );
436 }
437
438 QString OCCViewer_ViewFrame::getVisualParameters()
439 {
440   QStringList params;
441   QStringList splitParams;
442   if( mySplitMode != -1 && myViewsMode.count() != 0 ) {
443     splitParams << QString::number( mySplitMode );
444     foreach ( int aViewMode, myViewsMode )
445       splitParams << QString::number( aViewMode );
446     params.append( splitParams.join("*") );
447   }
448   else
449     params.append( QString::number( mySplitMode ) );
450   int maximizedView = 999;
451   for ( int i = BOTTOM_RIGHT; i <= TOP_RIGHT && i < myViews.count(); i++) {
452     if ( getView(i)->isVisible() )
453       maximizedView = ( maximizedView != -1 ) ? ( maximizedView == 999 ? i : -1 ) : ( maximizedView );
454     params << getView(i)->getVisualParameters();
455   }
456   params.prepend( QString::number( maximizedView ) );
457   return params.join( "|" );
458 }
459
460 void OCCViewer_ViewFrame::setVisualParameters( const QString& parameters ) 
461 {
462   QStringList params = parameters.split( "|" );
463   if ( params.count() > 1 ) {
464     int maximizedView = params[0].toInt();
465     if ( myViews.count() < params.count()-2 )
466       createSubViews(); // secondary views are not created yet, but should be
467
468     for ( int i = 2; i < params.count(); i++ ) {
469       int idx = i-2;
470       getView( idx )->setVisualParameters( params[i] );
471     }
472
473     QStringList aSplitParams = params[1].split("*");
474     if( aSplitParams.count() > 1 ) {
475       mySplitMode = aSplitParams[0].toInt();
476       for( int i = 1; i < aSplitParams.count(); i++ )
477         myViewsMode << aSplitParams[i].toInt();
478     }
479     if( mySplitMode != -1 )
480       splitSubViews();
481     else
482       onMaximizedView( getView( maximizedView ), true ); // set proper sub-window maximized
483   }
484   else {
485     // handle obsolete versions - no parameters for xy, yz, xz views
486     getView(MAIN_VIEW)->setVisualParameters( parameters );
487   }
488 }
489
490 SUIT_CameraProperties OCCViewer_ViewFrame::cameraProperties()
491 {
492   // view frame does not have camera properties
493   return SUIT_CameraProperties();
494 }
495
496 void OCCViewer_ViewFrame::updateWindowTitle(OCCViewer_ViewWindow* theView)
497 {
498   if ( !theView )
499     return;
500   QString title;
501   switch ( theView->get2dMode() ) {
502   case No2dMode:
503     title = "3D"; break;
504   case XYPlane:
505     title = "YX"; break;
506   case XZPlane:
507     title = "XZ"; break;
508   case YZPlane:
509     title = "YZ"; break;
510   default:
511     break;
512   }
513   if ( !title.isEmpty() )
514     theView->setWindowTitle( windowTitle() + " - " + title );
515 }
516
517 void OCCViewer_ViewFrame::enableSelection( bool isEnabled )
518 {
519   foreach (OCCViewer_ViewWindow* aView, myViews) {
520     aView->enableSelection(isEnabled); 
521   }
522 }
523
524 void OCCViewer_ViewFrame::enablePreselection( bool isEnabled )
525 {
526   foreach (OCCViewer_ViewWindow* aView, myViews) {
527     aView->enablePreselection(isEnabled); 
528   }
529 }