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