]> Creatis software - creaImageIO.git/blob - src2/creaImageIOWxGimmickView.cpp
correction sur la sélection.
[creaImageIO.git] / src2 / creaImageIOWxGimmickView.cpp
1 #include <creaImageIOWxGimmickView.h>
2 #include <creaImageIOWxTreeView.h>
3 #include <creaImageIOSystem.h>
4 using namespace crea;
5 // Icons
6 #include "icons/accept.xpm"
7 #include "icons/add.xpm"
8 #include "icons/folder-down.xpm"
9 #include "icons/page-down.xpm"
10 #include "icons/remove.xpm"
11 #include "icons/database-add.xpm"
12 #include "icons/help.xpm"
13
14 #include <wx/imaglist.h>
15 #include<boost/filesystem/operations.hpp>
16
17 namespace creaImageIO
18 {
19    
20   //======================================================================
21   // The ids of the different tools
22   enum
23     {
24       TOOL_ADDFILES_ID = 1,
25       TOOL_ADDDIR_ID = 2,
26       TOOL_REMOVE_ID = 3,
27       TOOL_ADDDATABASE_ID = 4,
28       TOOL_HELP_ID = 5
29     };
30   //======================================================================
31
32   //================================================================
33   // 
34   const int icon_number = 7;
35   // Icon ids
36   typedef enum
37     {
38       Icon_accept,
39       Icon_add,
40       Icon_folder_down,
41       Icon_page_down,
42       Icon_remove,
43       Icon_database_add,
44       Icon_help
45     }
46     icon_id;
47   //================================================================
48
49   //================================================================
50   /*
51   const icon_id Icon[5] = { Icon_Database,  
52                             Icon_Patient,
53                             Icon_Study,
54                             Icon_Series,
55                             Icon_Image };
56   */
57   //================================================================
58
59
60   //======================================================================
61   // CTor
62   WxGimmickView::WxGimmickView(Gimmick* gimmick,
63                                wxWindow *parent, 
64                                const wxWindowID id,
65                                const wxPoint& pos, const wxSize& size,
66                                int min_dim,
67                                    int max_dim,
68                                int number_of_threads)
69     : wxPanel(parent,id,pos,size),
70       GimmickView(gimmick, number_of_threads),
71       mProgressDialog(0),
72       mConstructed(false)
73   {
74     GimmickDebugMessage(1,"WxGimmickView::WxGimmickView"
75                         <<std::endl);
76     // Sets the current directory to the home dir
77     mCurrentDirectory =  std2wx(gimmick->GetHomeDirectory());
78
79      // Connect the AddProgress callback
80     gimmick->ConnectAddProgressObserver
81       ( boost::bind( &WxGimmickView::OnAddProgress , this, _1 ) );
82
83     // Create the list of icons (mIcon)
84     CreateIconList();
85
86     // Global sizer
87     wxBoxSizer  *sizer = new wxBoxSizer(wxVERTICAL);
88
89     // Create the tool bar
90     CreateToolBar(); 
91     sizer->Add( mToolBar ,0, wxGROW  ,0);
92
93     // Split part below toolbar into notebook for views and panel
94     // for preview, messages...
95     mSplitter = new wxSplitterWindow( this , -1);
96  
97    
98     // Notebook
99     mNotebook = new wxNotebook(mSplitter,
100                                -1,wxDefaultPosition, wxDefaultSize, 0);
101
102     //Gimmick
103     mGimmick=gimmick;
104
105       
106     mSelectionMaxDimension= max_dim;
107     mSelectionMinDimension= min_dim;
108     
109     // Create the views
110     CreateTreeViews();
111
112     // Bottom panel 
113     mBottomPanel = new wxPanel(mSplitter,-1);
114     
115           wxBoxSizer    *bottom_sizer = new wxBoxSizer(wxVERTICAL); //HORIZONTAL);
116     
117     
118     // Previewer
119     mViewer = new WxViewer(mBottomPanel, wxID_ANY, wxT("Gimmick! Viewer"),wxDefaultPosition, wxDefaultSize );
120         pointers.push_back(new ImagePointerHolder(GetDefaultImage()));
121         mViewer->SetImageVector(pointers);
122         mViewer->StartPlayer();
123
124
125     bottom_sizer->Add(mViewer,1,wxGROW,1);
126     //    mViewer->Show();
127
128           mText = new wxStaticText(mBottomPanel, wxID_ANY, wxT("Welcome to Gimmick!"));
129           bottom_sizer->Add(mText,0,wxGROW,0);
130
131           
132           
133     mBottomPanel->SetSizer(bottom_sizer);
134
135     // Splitting
136     int hsize = size.GetHeight();
137
138     int top_minsize = 450;
139     int bottom_minsize = 50;
140
141     mSplitter->SetMinimumPaneSize( bottom_minsize );
142     mSplitter->SplitHorizontally( mNotebook, mBottomPanel, 
143                                   top_minsize);
144
145     sizer->Add( mSplitter,1,wxGROW  ,0);
146
147
148     SetSizer( sizer );     
149     SetAutoLayout(true);
150     Layout();
151     
152     mConstructed = true;
153   }
154   //======================================================================
155
156   //======================================================================
157   /// Destructor
158   WxGimmickView::~WxGimmickView()
159   {
160         // stop the viewer before application exit.
161         mViewer->StopPlayer();
162     GimmickDebugMessage(1,"WxGimmickView::~WxGimmickView"
163                         <<std::endl);
164   }
165   //======================================================================
166   
167   //======================================================================
168   /// Creates the tool bar
169   void WxGimmickView::CreateToolBar()
170   {
171     long style = wxTB_HORIZONTAL | wxNO_BORDER | wxTB_TEXT;
172     mToolBar = new wxToolBar(this,-1,wxDefaultPosition,wxDefaultSize,
173                              style);
174
175     mToolAddFile = mToolBar->AddTool( TOOL_ADDFILES_ID, 
176                                       _T("Add file(s)"),
177                                       mIcon->GetBitmap(Icon_page_down),
178                                       _T("Add one or more file to database")
179                                       );
180     mToolAddDir = mToolBar->AddTool( TOOL_ADDDIR_ID, 
181                                       _T("Add folder"),
182                                       mIcon->GetBitmap(Icon_folder_down),
183                                       _T("Add the content of a folder to database")
184                                       );
185     mToolRemove = mToolBar->AddTool( TOOL_REMOVE_ID, 
186                                       _T("Remove"),
187                                       mIcon->GetBitmap(Icon_remove),
188                                       _T("Remove selected items")
189                                       );
190     mToolAddDatabase = mToolBar->AddTool( TOOL_ADDDATABASE_ID, 
191                                       _T("Open database"),
192                                       mIcon->GetBitmap(Icon_database_add),
193                                       _T("Open a local or distant database")
194                                       );
195     mToolHelp = mToolBar->AddTool( TOOL_HELP_ID, 
196                                       _T("Help"),
197                                       mIcon->GetBitmap(Icon_help),
198                                       _T("Open help window")
199                                       );
200     //const wxBitmap& bitmap1, const wxString& shortHelpString = "", wxItemKind kind = wxITEM_NORMAL)
201
202     mToolBar->Realize();
203   }
204   //======================================================================
205
206  
207   //======================================================================
208   /// Create the tree view for TreeHandler provided
209   void WxGimmickView::CreateTreeView( TreeHandler* h)
210   {
211     std::string name(h->GetTree().GetAttribute("Name"));
212     GimmickMessage(2,"Creating the tree view for '"<<
213                    name<<"'"<<std::endl);
214     // Create the WxTreeView
215     WxTreeView* view = new WxTreeView(h,this,mNotebook,-1);
216
217     // TO DO : TEST THAT A VIEW WITH SAME NAME IS NOT
218     // ALREADY IN THE MAP
219     GetTreeViewMap()[name] = view;
220
221     // Add Notebook page
222     mNotebook->AddPage( view, crea::std2wx(name) );
223
224   }
225
226   //======================================================================
227   void WxGimmickView::GetSelectedImages(std::vector<vtkImageData*>& s, int dim)
228   {
229         std::vector<std::string> files;
230         GetTreeViewMap()["Local database"]->GetSelectedAsString(files);
231         ReadImagesNotThreaded(s,files,dim);
232   }
233   //======================================================================
234
235   //======================================================================
236   void WxGimmickView::GetSelectedFiles(std::vector<std::string>& s)
237   {
238         GetTreeViewMap()["Local database"]->GetSelectedAsString(s);
239   }
240   //======================================================================
241
242   //======================================================================
243   void WxGimmickView::GetImages(int dim, 
244                                 const std::vector<std::string>& files, 
245                                 std::vector<vtkImageData*>& s)
246   {
247         ReadImagesNotThreaded(s,files,dim);
248   }
249   //======================================================================
250
251
252   //=================================================
253   void WxGimmickView::CreateIconList()
254   {
255     // Size of the icons;
256     int size = 24;
257
258     wxIcon icons[20];
259     // should correspond to Icon_xxx enum
260     icons[Icon_accept] = wxIcon(accept_xpm);
261     icons[Icon_add] = wxIcon(add_xpm);
262     icons[Icon_folder_down] = wxIcon(folder_down_xpm);
263     icons[Icon_page_down] = wxIcon(page_down_xpm);
264     icons[Icon_remove] = wxIcon(remove_xpm);
265     icons[Icon_database_add] = wxIcon(database_add_xpm);
266     icons[Icon_help] = wxIcon(help_xpm);
267
268     //   unsigned int NbIcons = 8;
269     // Make an image list containing small icons
270     mIcon = new wxImageList(size,size,true);
271     
272     // Make all icons the same size = size of the first one
273     int sizeOrig = icons[0].GetWidth();
274     for ( size_t i = 0; i < icon_number; i++ )
275       {
276         if ( size == sizeOrig )
277           {
278             mIcon->Add(icons[i]);
279           }
280         else
281           {
282             mIcon->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
283           }
284       }
285   }
286   //=================================================
287
288
289   //=================================================
290   void WxGimmickView::OnAddFiles(wxCommandEvent& event)
291   {
292    long style = wxOPEN | wxFILE_MUST_EXIST | wxFD_MULTIPLE;
293     std::string wc("*.*");
294     wxFileDialog* FD = new wxFileDialog( 0, 
295                                          _T("Select file"),
296                                          _T(""),
297                                          _T(""),
298                                          crea::std2wx(wc),
299                                          style,
300                                          wxDefaultPosition);
301     
302     if (FD->ShowModal()==wxID_OK)
303       {
304         wxBusyCursor busy;
305
306         wxArrayString files;
307         FD->GetPaths(files);
308         unsigned int i;
309         std::vector<std::string> filenames;
310         for (i=0;i<files.GetCount();++i)
311         {
312           filenames.push_back(wx2std(files[i]));
313           GimmickMessage(2,"Adding File "<<files[i]<<"."<<std::endl);
314         }
315
316         mProgressDialog = 
317           new wxProgressDialog(_T("Adding file(s)"),
318                                _T(""),
319                                1000,
320                                this,
321                                wxPD_ELAPSED_TIME |
322                                //                              wxPD_ESTIMATED_TIME | 
323                                //                              wxPD_REMAINING_TIME |
324                                wxPD_CAN_ABORT );
325
326         // TO DO : select the current tree handler
327         mGimmick->AddFiles("Local database",filenames);
328
329         mProgressDialog->Pulse(_T("Updating view..."));
330
331         UpdateTreeViewLevel("Local database",1);
332         delete mProgressDialog;
333         DisplayAddSummary();    
334       }
335         
336   }
337   //=================================================
338
339   //=================================================
340   void WxGimmickView::OnAddDir(wxCommandEvent& event)
341   {
342     long style = wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST;
343     wxDirDialog* FD = 
344       new wxDirDialog( 0, 
345                        _T("Select directory"),
346                        mCurrentDirectory,
347                        style);
348     
349     if (FD->ShowModal()==wxID_OK)
350       {
351         
352                   std::string dirname = wx2std (FD->GetPath());
353                   bool recurse =  isNeedRecursive(dirname);
354                   if (recurse)
355                  {
356              recurse = wxMessageBox(_T("Recurse into sub-directories ?"),  _T("Scan directory"),         wxYES_NO,this ) == wxYES ? true : false;
357                  }
358                 
359                 wxBusyCursor busy;
360                 wxString title(_T("Adding directory"));
361                 if (recurse) 
362                 title = _T("Adding directory (recursive)");
363                 mProgressDialog = 
364                 new wxProgressDialog(_T("Adding directory"),
365                                         _T(""),
366                                         1000,
367                                         this,
368                                         wxPD_ELAPSED_TIME |
369                                         //                             wxPD_ESTIMATED_TIME | 
370                                         //                             wxPD_REMAINING_TIME |
371                                         wxPD_CAN_ABORT );
372                 
373                 mCurrentDirectory = FD->GetPath();  
374                 
375                 // TO DO : select the current tree handler
376                 mGimmick->AddDir("Local database",dirname,recurse);
377                 
378                 mProgressDialog->Pulse(_T("Updating view..."));
379                 
380                 UpdateTreeViewLevel("Local database",1);
381                 delete mProgressDialog;
382                 DisplayAddSummary();
383           }
384   }
385
386     //=================================================
387    // Test a directory to know if contains sub-directory to analyze
388   bool WxGimmickView::isNeedRecursive(std::string i_name)
389   {
390       boost::filesystem::directory_iterator iter(i_name), end_iter;
391           bool bfindir = false;
392                   for(; iter != end_iter; ++iter)
393                   {
394                           if(boost::filesystem::is_directory(*iter))
395                           {
396                                   return true;
397                           }
398                   }
399                   return false;
400   }
401   //=================================================
402
403   //=================================================
404   void WxGimmickView::OnSelectionChange(const std::vector<tree::Node*>& sel, bool isSelection, int selection, bool needProcess)
405   {      
406     GimmickDebugMessage(5,
407                         "WxGimmickView::OnSelectionChange"
408                         <<std::endl);
409     wxBusyCursor busy;
410         bool valid=true;
411         
412         if(sel.size()==0)
413         {
414                 
415                 valid= ValidateSelected(NULL,
416                                 mSelectionMinDimension,
417                                 mSelectionMaxDimension );
418         }
419         else if(needProcess)
420         {
421                 ResetExtent();
422                 std::vector<tree::Node*>::const_iterator i;
423                 for(i=sel.begin();i!=sel.end()&&valid;++i)
424                 {
425                         valid= ValidateSelected((*i),
426                                 mSelectionMinDimension,
427                                 mSelectionMaxDimension );
428                 }
429         }
430         else if(isSelection)
431         {
432                 valid= ValidateSelected(sel.front(),
433                                 mSelectionMinDimension,
434                                 mSelectionMaxDimension );
435         }
436         else
437         {
438                 ResetExtent();
439                 std::vector<tree::Node*>::const_iterator i;
440                 for(i=sel.begin();i!=sel.end()&&valid;++i)
441                 {
442                         valid= ValidateSelected((*i),
443                                 mSelectionMinDimension,
444                                 mSelectionMaxDimension );
445                 }
446         }
447         
448     mText->SetLabel(crea::std2wx(GetMessage()));
449     /*if(valid)
450       {
451         ReadImageThreaded(sel);
452       }
453     else
454       {
455                   ClearSelection();
456       }*/
457         ReadImageThreaded(sel);
458
459     
460    }
461
462   //==================================================
463
464   //==================================================
465   ///Reads Images (Threaded)
466   void WxGimmickView::ReadImageThreaded(const std::vector<tree::Node*>& sel)
467   {     
468    GimmickDebugMessage(5,
469                        "ReadImageThreaded"
470                        <<std::endl);
471    int maxprio = GetMaximalPriority();
472    int prio = maxprio + 2000;
473
474    if(sel.size()>0)
475    {
476    //First load the selected images
477    mCurImageItemToShow = sel.front();
478    pointers.clear();
479    int index = 0;
480    std::vector<tree::Node*>::const_iterator selected;
481    for(selected=sel.begin();selected!=sel.end();++selected)
482      {
483        GimmickDebugMessage(5,
484                            "Requesting image from selected "
485                            <<(*selected)->GetAttribute("FullFileName")
486                            <<std::endl);
487            ImagePointerHolder* ph=new ImagePointerHolder(GetDefaultImage());
488            pointers.push_back(ph);
489        RequestReading(*selected,prio,index,ph);
490        //       AddEntryToMap(*selected);
491        prio--;
492        index++;
493      }
494         mViewer->SetImageVector(pointers);
495         //Going up
496         prio = maxprio + 20;
497         std::vector<tree::Node*> up;
498         GetTreeViewMap()["Local database"]->GetNodes(up,true);
499         std::vector<tree::Node*>::iterator iterUp;
500         for(iterUp=up.begin();iterUp!=up.end();++iterUp)
501         {
502                 GimmickDebugMessage(5,
503                                 "Requesting image from neighbors up "
504                                 <<(*iterUp)->GetAttribute("FullFileName")
505                                 <<std::endl);
506                 ImagePointerHolder* ph=new ImagePointerHolder(GetDefaultImage());
507                 RequestReading(*iterUp,prio,-1,ph);
508                 //              AddEntryToMap(*iterUp);
509                 prio--;
510                 if (prio == maxprio) break;
511         }
512
513         //Going down
514         prio = maxprio + 19;
515         std::vector<tree::Node*> down;
516         GetTreeViewMap()["Local database"]->GetNodes(down,false);
517         std::vector<tree::Node*>::iterator iterDown;
518         for(iterDown=down.begin();iterDown!=down.end();++iterDown)
519         {
520                 GimmickDebugMessage(5,
521                                 "Requesting image from neighbors down "
522                                 <<(*iterDown)->GetAttribute("FullFileName")
523                                 <<std::endl);
524                 ImagePointerHolder* ph=new ImagePointerHolder(GetDefaultImage());
525                 RequestReading(*iterDown,prio,-1,ph);
526                 //              AddEntryToMap(*iterDown);
527                 prio--;
528                 if (prio == maxprio) break;
529         }
530    }
531    else
532    {
533            pointers.clear();
534            ImagePointerHolder* ph=new ImagePointerHolder(GetDefaultImage());
535            pointers.push_back(ph);
536            mViewer->SetImageVector(pointers);
537    }
538   }
539
540   //==================================================
541
542   //==================================================
543
544   //==================================================
545    void  WxGimmickView::OnInternalIdle()
546   {
547    if (!mConstructed) return;
548    static bool first_time = true;
549    if (false)
550    {
551         first_time = false;
552      }
553    //   GimmickMessage(1,"WxGimmickView : Refresh viewer"<<std::endl);
554         //  mViewer->StartPlayer();
555    if(mViewer)
556    {
557            mViewer->RefreshIfNecessary();
558    }
559   }
560
561    //==================================================
562
563   //==================================================
564    void  WxGimmickView::ClearSelection()
565   {
566         pointers.clear();
567         pointers.push_back(new ImagePointerHolder(GetDefaultImage()));
568         mViewer->SetImageVector(pointers);
569         mViewer->RefreshIfNecessary();
570         ResetExtent();
571   }
572   
573   //=================================================
574  
575   //=================================================
576   void WxGimmickView::OnRemove(wxCommandEvent& event)
577   {
578         //TODO Select current tree handler       
579     wxBusyCursor busy;
580     GetTreeViewMap()["Local database"]->RemoveSelected();
581
582         ClearSelection();
583   }
584   //=================================================
585
586   //=================================================
587   /// AddProgress Gimmick callback
588   void WxGimmickView::OnAddProgress( Gimmick::AddProgress& p)
589   {
590
591     char mess[200];
592    
593         sprintf(mess,"%i dirs : %i files :\n            %i handled - %i added",
594            p.GetNumberScannedDirs(),
595            p.GetNumberScannedFiles(),
596            p.GetNumberHandledFiles(),
597            p.GetNumberAddedFiles());
598     //    std::cout << "OnAddProgress "<<mess<<std::endl;
599     wxString s(wxString::From8BitData(mess));
600     //  std::cout << "Pulse"<<std::endl;
601     if (!mProgressDialog->Pulse(s)) 
602       {
603         p.SetStop();
604       }
605     //  std::cout << "OnAddProgress ok"<<std::endl;
606   }
607   //=================================================
608
609   //=================================================
610   void WxGimmickView::DisplayAddSummary()
611   {
612     const Gimmick::AddProgress& p = mGimmick->GetAddProgress();
613     std::stringstream mess;
614     mess << "Dirs \tscanned\t: " << p.GetNumberScannedDirs()  << "\n";
615     mess << "Files\tscanned\t: " << p.GetNumberScannedFiles() << "\n";
616     mess << "Files\thandled\t: " << p.GetNumberHandledFiles() << "\n\n";
617     mess << "Files\tadded  \t: " << p.GetNumberAddedFiles()   << "\n\n";
618
619     /*    char times[500];
620     sprintf(times,"Time to parse dir \t\t: %ld ms \t%d°/o\nTime to read files info \t: %ld ms \t%d°/o\nTime to update structs \t: %ld ms \t%d°/o\nTime to update database \t: %ld ms \t%d°/o\nTotal time \t\t\t: %ld ms",
621             summary.parse_time,
622             (int)( summary.parse_time*100./summary.total_time),
623             summary.file_scan_time,
624             (int)(summary.file_scan_time*100./summary.total_time),
625             summary.update_structs_time,
626             (int)(summary.update_structs_time*100./summary.total_time),
627             summary.update_database_time,
628             (int)(summary.update_database_time*100./summary.total_time),
629             summary.total_time );
630     
631     mess << times;
632     */
633     wxMessageBox(std2wx(mess.str()),_T("Addition result"),wxOK,this);
634   }
635
636    //=================================================
637
638    //=================================================
639   BEGIN_EVENT_TABLE(WxGimmickView, wxPanel)
640     EVT_TOOL(TOOL_ADDFILES_ID, WxGimmickView::OnAddFiles)
641     EVT_TOOL(TOOL_ADDDIR_ID, WxGimmickView::OnAddDir)
642         EVT_TOOL(TOOL_REMOVE_ID, WxGimmickView::OnRemove)
643   END_EVENT_TABLE()
644   //=================================================
645
646 } // EO namespace creaImageIO
647
648