]> Creatis software - creaImageIO.git/blobdiff - src/creaImageIOWxGimmick.cpp
*** empty log message ***
[creaImageIO.git] / src / creaImageIOWxGimmick.cpp
index 7bfed5b624ed7a85adf498ebb648410652db836e..63470ba141b56f8d126d92715499c4a1fc90b79d 100644 (file)
@@ -19,7 +19,8 @@
 #include <vtkCamera.h>
 #include <vtkRenderer.h>
 
-#include<wx/filefn.h>
+#include <wx/filefn.h>
+//#include <wx/tipwin.h>
 
 using namespace crea;
 
@@ -62,6 +63,8 @@ namespace creaImageIO
       PopUp_Settings = 501,
       PopUp_About    = 502,
       PopUp_User = WxGimmick::UserMenuFirstId,
+      PopUp_SaveAs = 701,
+      PopUp_AddToFavorites = 702
     };
   //================================================================
 
@@ -209,18 +212,6 @@ namespace creaImageIO
 
 
 
-  //================================================================
-  class WxGimmickSettingsDialog : public wxDialog
-  {
-  public:
-    WxGimmickSettingsDialog(wxWindow *parent);
-    ~WxGimmickSettingsDialog();
-    
-    
-  };
-  //================================================================
-
-
 
 
 
@@ -255,14 +246,26 @@ namespace creaImageIO
   //================================================================
   //================================================================
   WxGimmick::WxGimmick(wxWindow *parent, 
-                                                  wxWindowID id,
-                                                  const wxPoint& pos,
-                                                  const wxSize& size,
-                                                  int threads)
+                      wxWindowID id,
+                      const wxPoint& pos,
+                      const wxSize& size,
+                      int image_type,
+                      int threads)
     : wxPanel(parent,id,pos,size),
+      mSelectionType(image_type),
       mSaveConfigurationOnClose(true),
       mReader(threads)
   {
+    // Initialize image size corresponding to current selection
+    switch (mSelectionType) 
+      {
+      case GIMMICK_2D_IMAGE_SELECTION : mSelectionMaxImageDimension = 2; break;
+      case GIMMICK_3D_IMAGE_SELECTION : mSelectionMaxImageDimension = 3; break;
+      case GIMMICK_4D_IMAGE_SELECTION : mSelectionMaxImageDimension = 4; break;
+      default : mSelectionMaxImageDimension = 0;
+      }
+
+
     // Start the threads ...
     mReader.Start();
 
@@ -333,9 +336,15 @@ namespace creaImageIO
     // Image sizer
     wxBoxSizer *isizer = new wxBoxSizer(wxHORIZONTAL  );
     mPanelImage->SetSizer( isizer ); 
-  
+    // Notebook
+    mwxNotebook = new wxNotebook(mSplitter2,
+                                -1,wxDefaultPosition, wxDefaultSize, 0);
+
+
+    
     // Fields view (bottom)
-    mFieldsView = new WxGimmickFieldsView(mSplitter2,-1,
+    mFieldsView = new WxGimmickFieldsView(mwxNotebook,-1,
                                            wxDefaultPosition,
                                            wxDefaultSize,0);
 
@@ -350,16 +359,20 @@ namespace creaImageIO
        GetSettings().BgColour(DicomNode::Series),
        GetSettings().Colour(DicomNode::Image),
        GetSettings().BgColour(DicomNode::Image));
+    mwxNotebook->AddPage( mFieldsView, _T("Dicom fields"));
     
-    
-
+    // Help 
+    mHelp = new WxGimmickHelp(mwxNotebook);
+    mwxNotebook->AddPage( mHelp, _T("Help"));    
+    // Splitting
     int wsize = size.GetWidth();
     int hsize = size.GetHeight();
     int previewhsize = 150;
     int previewwsize = 400;
 
     mSplitter2->SetMinimumPaneSize( previewhsize );
-    mSplitter2->SplitHorizontally( mPanelImage, mFieldsView, 
+    mSplitter2->SplitHorizontally( mPanelImage, mwxNotebook, //mFieldsView, 
                                   hsize - previewhsize);
   
     rsizer->Add( mSplitter2,1,wxGROW  ,0);
@@ -369,7 +382,7 @@ namespace creaImageIO
     rpanel->Layout(); 
   
     // previewer
-    mInteractor = new wxVTKRenderWindowInteractor(mPanelImage,-1);
+       mInteractor = new crea::creawxVTKRenderWindowInteractor(mPanelImage,-1);
     mInteractor->UseCaptureMouseOn();  
   
     mViewer    = vtkImageViewer2::New();
@@ -399,6 +412,16 @@ namespace creaImageIO
 
     ShowImage(mReader.GetImage(""));
 
+    // Show help if no collection
+    if (GetDicomDatabaseList().size()==0)
+      {
+       mwxNotebook->SetSelection(1);
+      } 
+    else
+      {
+       mwxNotebook->SetSelection(0);
+      }
+    //    mJustStarted = true;
   }
   //================================================================
     
@@ -695,8 +718,7 @@ namespace creaImageIO
        mTreeListCtrl->SetItemText(item,std2wx(lab));
       }
     else 
-      {
-       
+      {        
        int c = 0;
        Settings::ColumnListType::iterator col;
        // If Study and Series level are merged and node type is Series
@@ -765,7 +787,7 @@ namespace creaImageIO
 
   //================================================================
   void WxGimmick::UpdateColumnsTitles(wxTreeItemId& item,
-                                                   DicomNode::Type t)
+                                      DicomNode::Type t)
   {
     //    std::cout << "Update columns titles "<<t<<std::endl;
     int c = 0;
@@ -847,6 +869,9 @@ namespace creaImageIO
        boost::filesystem::change_extension(filepath,GetDatabaseExtension());
        if ( boost::filesystem::exists(filepath) )
          {
+                 boost::filesystem::remove(filepath);  
+                         /* 
+                         LG : works on Linux but not Windows :
            if ( ! boost::filesystem::remove(filepath) )
              {
                wxMessageBox(_T("Could not overwrite ")
@@ -854,8 +879,10 @@ namespace creaImageIO
                             _T("Error"),
                             wxOK,this);
                return;
+               
        
              }
+                 */
          }
       }
     
@@ -891,9 +918,11 @@ namespace creaImageIO
          }
       }
 
+    if (GetDicomDatabaseList().size()==0) mFieldsView->UpdateFields(db);
     GetDicomDatabaseList().push_back(db);
     UpdateDicomDatabaseView(db);
 
+
   }
   //================================================================
 
@@ -903,10 +932,13 @@ namespace creaImageIO
   {
     wxBusyCursor busy;
     //    std::cout << "WxGimmick : Reading config"<<std::endl;
+    LoadOrCreateFavoritesDatabase();
 
-    //    std::cout << "==> Loading collections from '"<<mDatabaseListFile
+    //    std::cout <<     
+    creaMessage("Gimmick!",1,"Gimmick! : ==> Loading collections from '"<<mDatabaseListFile<<"'"<<std::endl);
     //       <<"'"<<std::endl;
 
+
     std::ifstream s;
     s.open(mDatabaseListFile.c_str());
     if (s.good())
@@ -941,7 +973,7 @@ namespace creaImageIO
              }
            else 
              {
-               //          std::cout << "    ... ERROR !"<<std::endl;
+               creaMessage("Gimmick!",1,"           ==> ERROR opening collection '"<<tokens[0]<<"'"<<std::endl);
                delete db;
              }
          }
@@ -949,7 +981,7 @@ namespace creaImageIO
        }
        else 
        {
-               std::cout << "ERROR opening "<<mDatabaseListFile<<std::endl;
+         creaMessage("Gimmick!",1,"           ==> File does not exist. It will be created on exit (if you already ran Gimmick! and exited normally, this is not normal. Send a bug report).");
        }
 
        
@@ -995,6 +1027,13 @@ namespace creaImageIO
   }
   //================================================================
 
+  //================================================================
+  void WxGimmick::LoadOrCreateFavoritesDatabase()
+  {
+    // TODO
+  }
+  //================================================================
+
   /*
   //================================================================
   void  WxGimmick::OnClose(wxCloseEvent& event)
@@ -1024,16 +1063,66 @@ namespace creaImageIO
   //================================================================
 
   //================================================================
-  void WxGimmick::OnItemExpanded(wxTreeEvent& event)                   
+  void WxGimmick::LoadChildren(wxTreeItemId& id)
   {
+    TreeItemData *item = (TreeItemData *)mTreeListCtrl->GetItemData(id);
+    if (item)
+      {
+       if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
+            ( ! item->GetDicomNode()->ChildrenLoaded() ) )
+         {
+           
+           // If children not already loaded : do it 
+           if (
+               item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
+               (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
+               > 0 )
+             {
+               // Some new children loaded
+               // Sort them
+               if (mSettings.HasActiveComparator
+                   (item->GetDicomNode()->GetType()+1))
+                 {
+                   /*                  std::cout << "Sorting using '"
+                     << mSettings.GetActiveComparator
+                     (item->GetDicomNode()->GetType()+1).GetName() 
+                     << "' ... ";
+                   */
+                   item->GetDicomNode()->SortChildren
+                     ( mSettings.GetActiveComparator
+                       (item->GetDicomNode()->GetType()+1)
+                       );
+                   //                  std::cout << "ok"<<std::endl;
+                 }
+               // Update tree
+               DicomNode::ChildrenListType::iterator i;
+               for (i=item->GetDicomNode()->GetChildrenList().begin();
+                    i!=item->GetDicomNode()->GetChildrenList().end();
+                    i++)
+                 {
+                   UpdateDicomNodeView(*i,id);
+                 }
+             }
+           // EO If children not already loaded 
+         }
+      } 
+  }
+  //================================================================
+
 
+  //================================================================
+  void WxGimmick::OnItemExpanded(wxTreeEvent& event)                   
+  {
     //    std::cout << "* Expanded *"<<std::endl;
     //  }
 
     wxBusyCursor busy;
     
     wxTreeItemId itemId = event.GetItem();
+    LoadChildren(itemId);
+    
+    return;
+
     // expand if collapsed and collapse if expanded ...
     TreeItemData *item = 
       (TreeItemData *)mTreeListCtrl->GetItemData(itemId);
@@ -1173,7 +1262,6 @@ namespace creaImageIO
   
   void WxGimmick::OnItemRightClick(wxTreeEvent& event)
   {
-
     wxTreeItemId itemId = event.GetItem();
     if (itemId.IsOk())
       {
@@ -1184,8 +1272,6 @@ namespace creaImageIO
     event.Skip();
   }
   //=====================================================================
-  
-
 
   //=====================================================================
   void WxGimmick::ShowMenu(wxTreeItemId id, const wxPoint& pt)
@@ -1230,8 +1316,9 @@ namespace creaImageIO
          }
        if (data->IsDicomNode())
          {
-           /*
+           
            //      LG : BUGGY
+           /*
            std::string str("&Remove ");
            str += data->GetDicomNode()->GetTypeName();
            menu.Append(PopUp_Remove, std2wx(str));
@@ -1285,13 +1372,11 @@ namespace creaImageIO
       }
     GetEventHandler()->ProcessEvent(ev);
     //
-  
+
     if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
     menu.Append(PopUp_Settings, wxT("&Settings..."));
     menu.Append(PopUp_About, wxT("&About..."));
   
-
-  
     /*
       wxMenu* newmenu = new wxMenu;
       wxMenu* openmenu = new wxMenu;
@@ -1351,9 +1436,6 @@ namespace creaImageIO
       }
       }
     */
-
-
  
     PopupMenu(&menu, pt);
 #endif // wxUSE_MENUS
@@ -1366,7 +1448,7 @@ namespace creaImageIO
   // Pop up menu callbacks
   void  WxGimmick::OnPopUpAbout(wxCommandEvent& event)
   {
-    wxMessageBox( _T("Give me my medical images quick ! \n\n  (c) CREATIS-LRMN 2008\n"),
+    wxMessageBox( _T("Give me my medical images quick ! \n\n  (c) CREATIS-LRMN 2008\n      laurent.guigues@creatis.insa-lyon.fr"),
                  _T("Gimmick!"),
                  wxOK | wxICON_INFORMATION, this);
   }
@@ -1376,7 +1458,7 @@ namespace creaImageIO
   void  WxGimmick::OnPopUpSettings(wxCommandEvent& event)
   {
     WxGimmickSettingsDialog* s = 
-      new WxGimmickSettingsDialog(this);
+      new WxGimmickSettingsDialog(this,&mSettings);
     s->ShowModal();
     delete s;
   }
@@ -1390,7 +1472,6 @@ namespace creaImageIO
   }
   //=====================================================================
   
-
  
   //=====================================================================
   void  WxGimmick::OnPopUpOpenCollection(wxCommandEvent& event)
@@ -1420,22 +1501,21 @@ namespace creaImageIO
   void  WxGimmick::OnPopUpDeleteCollection(wxCommandEvent& event)
   {
     if (wxMessageBox(_T("This will physically delete the collection's file on disk and cannot be reverted. Proceed ?"),_T("Confirm"),wxYES_NO,this)==wxNO) return;
-    
+  
     wxBusyCursor busy;
 
-   
     //   std::cout << "OnPopUpClose"<<std::endl;
     //  wxTreeItemId id = event.GetId();
     TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
     DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
-
     wxRemoveFile(std2wx(r->GetFileName()));
     //   std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
     DeleteDicomDatabase(mItemOfMenu,r);
-    
   }
   //=====================================================================
-  
+
   void DisplayUpdateSummary( DicomDatabase::UpdateSummary& summary,
                             wxWindow* parent )
   {
@@ -1458,18 +1538,18 @@ namespace creaImageIO
            summary.update_database_time,
            (int)(summary.update_database_time*100./summary.total_time),
            summary.total_time );
-    
+
     mess << times;
-    
     wxMessageBox(std2wx(mess.str()),_T("Update summary"),wxOK,parent);
   }
-  
-  
+
+
   //=====================================================================
   void  WxGimmick::OnPopUpAddFile(wxCommandEvent& event)
   {
     long style = wxOPEN | wxFILE_MUST_EXIST | wxFD_MULTIPLE;
-    std::string wc("*.*");
+    std::string wc("*");
     wxFileDialog* FD = new wxFileDialog( 0, 
                                         _T("Select file"),
                                         mCurrentDirectory,
@@ -1477,7 +1557,7 @@ namespace creaImageIO
                                         std2wx(wc),
                                         style,
                                         wxDefaultPosition);
-    
+
     if (FD->ShowModal()==wxID_OK)
       {
        wxBusyCursor busy;
@@ -1725,25 +1805,111 @@ namespace creaImageIO
   }
   //=================================================
 
+
+
+
+
+
+
+
+  //================================================================
+  bool WxGimmick::IsImageSelectable(DicomNode* node)                   
+  {
+    int rows = node->ImageGetRows();
+    int cols = node->ImageGetColumns();
+    int frms = node->ImageGetFrames();
+    
+    //    std::cout << "R/C/F = " << rows << "/"<< cols <<"/"<<frms<<std::endl;
+
+    int dim = 0;
+    if (frms>0) dim=3;
+    else if (cols>0) dim=2;
+    else if (rows>0) dim=1;
+    
+    if (dim == 0) 
+      {
+       std::cout << "Unknown image dimension : cannot select !" 
+                 << std::endl;
+       return false;
+      }
+    else if (dim>mSelectionMaxImageDimension)
+      {
+       std::cout << "Selecting "<<dim<<"D images is not allowed !" 
+                 << std::endl;
+       return false;
+      }
+    
+    if ( mTreeListCtrl->GetSelectionSize() == 0 ) 
+      {
+       mCurrentSelectionImageSize[0] = cols;
+       mCurrentSelectionImageSize[1] = rows;
+       mCurrentSelectionImageSize[2] = frms;
+       return true;
+      }
+    else 
+      {
+       if ( dim == mSelectionMaxImageDimension )
+         {
+           std::cout << "Cannot add this image to selection : would result in a "<<dim+1<<"D image !" << std::endl;
+           return false;
+         }
+       if ( ( cols != mCurrentSelectionImageSize[0] ) ||
+            ( rows != mCurrentSelectionImageSize[1] ) ||
+            ( frms != mCurrentSelectionImageSize[2] ) )
+         {
+           std::cout << "Cannot add this image to selection : image size is incomptatible with currently selected images" << std::endl; 
+           return false;
+         }
+      }
+    //    std::cout << "Selecting : "<<node->ImageGetFullFileName() << std::endl;
+    return true;
+  }
+  //================================================================
+
   //================================================================
   void WxGimmick::OnSelChanging(wxTreeEvent& event)                   
   {
+    event.Veto();
     wxTreeItemId id = event.GetItem();
     if (!id.IsOk()) 
       {
-       std::cout << "ERROR : ID NOT OK"<<std::endl;
+       std::cout << "INTERNAL ERROR : ID NOT OK"<<std::endl;
        return;
       }
 
-    TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
 
-    event.Veto();
+    TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
     if (data->IsDicomNode())
       {
-       if ((data->GetDicomNode()>0)&&
-           ( data->GetDicomNode()->GetType()==DicomNode::Image))
+       if (data->GetDicomNode()>0)
          {
-           event.Allow();
+           // An image was selected 
+           if (data->GetDicomNode()->GetType()==DicomNode::Image)
+             {
+               if (IsImageSelectable(data->GetDicomNode())) event.Allow();
+             }
+           // A series was selected 
+           else if (data->GetDicomNode()->GetType()==DicomNode::Series)
+             {
+               // If images not loaded do it 
+               LoadChildren(id);
+               // can be selected if all its images can
+               wxTreeItemId child;
+               wxTreeItemIdValue cookie;
+               for (child = mTreeListCtrl->GetFirstChild(id,cookie);
+                    child.IsOk();
+                    child = mTreeListCtrl->GetNextChild(id,cookie))
+                 {    
+                   TreeItemData *cdata = 
+                     (TreeItemData *)mTreeListCtrl->GetItemData(child);
+                   if ((cdata->IsDicomNode())&&
+                       (cdata->GetDicomNode()>0)&&
+                       (cdata->GetDicomNode()->GetType()==DicomNode::Image)&&
+                       (!IsImageSelectable(cdata->GetDicomNode())))
+                     return;
+                 }
+               event.Allow();
+             }
          }
       }
   }
@@ -1817,15 +1983,15 @@ namespace creaImageIO
                //                                << nsib->GetFieldValue("FullFileName")
                //                                << "' prio="<<prio<<std::endl;
                mReader.Request(this,
-                               nsib->GetFieldValue("FullFileName"), 
+                               nsib->ImageGetFullFileName(), 
                                prio);
-               mImageFileNameToNode[nsib->GetFieldValue("FullFileName")] =
+               mImageFileNameToNode[nsib->ImageGetFullFileName()] =
                  nsib;
                prio--;
              }
            sib = GetTreeListCtrl()->GetNextSibling(sib);
          }
-       prio = maxprio + 1000;
+       prio = maxprio + 999;
        sib = GetTreeListCtrl()->GetPrevSibling(item);
        while (sib.IsOk())
          {
@@ -1836,9 +2002,9 @@ namespace creaImageIO
                //                                << nsib->GetFieldValue("FullFileName")
                //                                << "' prio="<<prio<<std::endl;
                mReader.Request(this,
-                               nsib->GetFieldValue("FullFileName"), 
+                               nsib->ImageGetFullFileName(), 
                                prio);
-               mImageFileNameToNode[nsib->GetFieldValue("FullFileName")] =
+               mImageFileNameToNode[nsib->ImageGetFullFileName()] =
                  nsib;
                prio--;
              }
@@ -1868,13 +2034,17 @@ namespace creaImageIO
   void WxGimmick::ShowImage(vtkImageData* im)
   {
     //  wxBusyCursor busy;
+    mViewer->SetInput( im );
+    mViewer->SetSlice( 0 );
     
+
     int x1,x2,y1,y2,z1,z2;
     double spx,spy,spz;
+    im->Update();
     im->GetSpacing(spx,spy,spz);
     im->GetExtent (x1,x2,y1,y2,z1,z2);
-    
     /*
+    std::cout << "-----------------------------"<<std::endl;
       std::cout << x1 << "-"<<x2<<std::endl; 
       std::cout << y1 << "-"<<y2<<std::endl; 
       std::cout << z1 << "-"<<z2<<std::endl; 
@@ -1902,19 +2072,39 @@ namespace creaImageIO
        mspy = spy;
        mspz = spz;
        
+       double *range = im->GetScalarRange();
+        mViewer->SetColorWindow(range[1] - range[0]);
+        mViewer->SetColorLevel(0.5 * (range[1] + range[0]));
+
+        mViewer->GetRenderer()->ResetCamera();
+       double bounds[6];
+
+
+        mViewer->GetRenderer()->ComputeVisiblePropBounds(bounds);
+
+        /*
+       std::cout <<"bounds : "<<bounds[0]<<","
+<<bounds[1]<<","
+<<bounds[2]<<","
+<<bounds[3]<<","
+<<bounds[4]<<","
+                 <<bounds[5]<<std::endl;
+        */
+        mViewer->GetRenderer()->ResetCameraClippingRange(bounds);
+       /*
        vtkCamera *camera = mViewer->GetRenderer()->GetActiveCamera();
        
        camera->SetViewUp ( spx*0, -spy*1, spz*0);
-       camera->SetPosition( spx*(x1+x2)/2, spy*(y1+y2)/2, -spz*10000000); 
+       camera->SetPosition( spx*(x1+x2)/2, spy*(y1+y2)/2, spz*10000000); 
        camera->SetFocalPoint   ( spx*(x1+x2)/2 , spy*(y1+y2)/2 , spz*0); 
        
        camera->ComputeViewPlaneNormal();
        camera->SetParallelScale(  spx*(x2-x1)/2.0 );
        
+       camera->Roll ( 180 );
+       */
       }
     
-    mViewer->SetInput( im );
-    mViewer->SetSlice( 0 );
     mInteractor->Render();
   } 
   //================================================================
@@ -1995,18 +2185,69 @@ namespace creaImageIO
   void  WxGimmick::OnInternalIdle()
   {
     ProcessImageEvents();
+    /*
+    if (mJustStarted)
+      {
+
+       mJustStarted = false;
+       }
+    */
+    //
   }
   //================================================================
  
 
+  //================================================================
+  // LG : For the moment any selection is valid but in the future 
+  // incomplete selections can be invalid...
+  bool WxGimmick::IsSelectionValid() 
+  { 
+    return (mTreeListCtrl->GetSelectionSize()>0); 
+  } 
+  //================================================================
+
+  //================================================================
+  void WxGimmick::GetSelectedFiles(std::vector<std::string>& f)
+  {
+    wxArrayTreeItemIds id;
+    // TO DO : TEST THAT STYLE IS MULTIPLE 
+    unsigned int nb = mTreeListCtrl->GetSelections(id);
+    f.clear();
+    for (unsigned int i=0; i<nb; ++i)
+      {
+       TreeItemData *data = 
+         (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
+       if ((data) && (data->IsDicomNode()))
+         {
+           if (data->GetDicomNode()->GetType()==DicomNode::Image)
+             {
+               f.push_back ( data->GetDicomNode()->ImageGetFullFileName() );
+             }
+           else if (data->GetDicomNode()->GetType()==DicomNode::Series)
+             {
+               DicomNode::ChildrenListType::iterator j;
+               for (j =data->GetDicomNode()->GetChildrenList().begin();
+                    j!=data->GetDicomNode()->GetChildrenList().end();
+                    j++) 
+                 {
+                   f.push_back((*j)->ImageGetFullFileName());
+                 }
+             }
+         }
+      }
+  }
+  //================================================================
 
   //================================================================
-  void WxGimmick::GetSelectedImages(std::vector<std::string>& f)
+  void WxGimmick::GetSelectedImages(std::vector<vtkImageData*>& f)
   {
     wxArrayTreeItemIds id;
     // TO DO : TEST THAT STYLE IS MULTIPLE 
     unsigned int nb = mTreeListCtrl->GetSelections(id);
     f.clear();
+
+    // Collect the brute vector of Image nodes
+    std::vector<DicomNode*> im;
     for (unsigned int i=0; i<nb; ++i)
       {
        TreeItemData *data = 
@@ -2015,7 +2256,8 @@ namespace creaImageIO
          {
            if (data->GetDicomNode()->GetType()==DicomNode::Image)
              {
-               f.push_back ( data->GetDicomNode()->GetFieldValue("FullFileName") );
+               im.push_back ( data->GetDicomNode() );
+
              }
            else if (data->GetDicomNode()->GetType()==DicomNode::Series)
              {
@@ -2024,11 +2266,95 @@ namespace creaImageIO
                     j!=data->GetDicomNode()->GetChildrenList().end();
                     j++) 
                  {
-                   f.push_back((*j)->GetFieldValue("FullFileName"));
+                   im.push_back ( *j );
                  }
              }
          }
       }
+    // Create the output data
+    if (im.size()==1) 
+      {
+       // Only one image : give it
+       vtkImageData* out = vtkImageData::New();
+       out->ShallowCopy(mReader.GetImage(im.front()->ImageGetFullFileName()));
+       f.push_back( out );
+      }
+    else if (im.size()>1)
+      {
+       vtkImageData* first = mReader.GetImage( im.front()->ImageGetFullFileName() );
+       if (first->GetDataDimension()==2) 
+         {     
+           // n2D to 3D
+           vtkImageData* out = vtkImageData::New();
+           out->CopyStructure(first);  
+           out->SetScalarType(first->GetScalarType());
+           int ext[6];
+           first->GetExtent(ext);
+           ext[5] = im.size();
+           out->SetExtent(ext);
+           // LG : TODO : Z Spacing  ?
+           //
+           // ==> to get an accurate ZSpacing from a Dicom set of files
+           // ==> you need a gdcm::SerieHelper
+           //  JPR
+           
+           out->AllocateScalars();
+           
+           //first->Print(std::cout);
+           //      out->Print(std::cout);
+           
+           int dim[3];
+           first->GetDimensions(dim);
+           unsigned long imsize = 
+             ( (unsigned long)first->GetScalarPointer(0,1,0)
+               - (unsigned long)first->GetScalarPointer(0,0,0))
+             *dim[1];
+
+           int slice = 0;
+           std::vector<DicomNode*>::iterator it;
+           for (it=im.begin(); it!=im.end(); ++it) 
+             {
+               //std::cout << "copying slice "<<slice <<std::endl;
+               vtkImageData* cur = mReader.GetImage( (*it)->ImageGetFullFileName() );
+               
+               void* src = cur->GetScalarPointer(0,0,0);
+               void* dst = out->GetScalarPointer(0,0,slice);
+               //              std::cout << "src="<<src<<std::endl;
+               //              std::cout << "dst="<<dst<<std::endl;
+               //              std::cout << "siz="<<imsize<<std::endl;
+               memcpy(dst,src,imsize);
+
+               /*
+               // verif
+               int ii,jj;
+               for (ii=1;ii<4;ii++) {
+                 for (jj=1;jj<4;jj++) {
+                   int x = (int)(ii*dim[0] / 4);
+                   int y = (int)(jj*dim[1] / 4);
+                   std::cout << cur->GetScalarComponentAsFloat(x,y,0,0)
+                             << " vs "
+                             << out->GetScalarComponentAsFloat(x,y,slice,0)
+                             << std::endl;
+                 }
+               }
+               */
+
+               slice++;
+             }
+           f.push_back(out);
+         }
+       else 
+         {
+           // n3D
+           std::vector<DicomNode*>::iterator it;
+           for (it=im.begin(); it!=im.end(); ++it) 
+             {
+               vtkImageData* out = vtkImageData::New();
+               out->ShallowCopy(mReader.GetImage((*it)->ImageGetFullFileName()));
+               f.push_back(out);
+             }
+         }
+      }
   }
   //================================================================
 
@@ -2052,7 +2378,7 @@ namespace creaImageIO
 
        if (data->GetDicomNode()->GetType()==DicomNode::Image)
        {
-       f.push_back ( data->GetDicomNode() ); //->GetFieldValue("FullFileName") );
+       f.push_back ( data->GetDicomNode() ); //->ImageGetFullFileName() );
        }  
        else if (data->GetDicomNode()->GetType()==DicomNode::Series)
        {
@@ -2061,8 +2387,7 @@ namespace creaImageIO
        j!=data->GetDicomNode()->GetChildrenList().end();
        j++) 
        {
-       f.push_back((*j)); //->GetFieldValue("FullFileName"));
-       }
+       f.push_back((*j)); //->ImageGetFullFileName() );        }
        }
        }
        */
@@ -2477,10 +2802,19 @@ namespace creaImageIO
     }
 
 
-
-
-
-
+    //====================================================================
+    void WxGimmick::ShowHelp()
+    {
+      /*
+      if (mHelpWindow==0)
+       {
+         mHelpWindow = new WxGimmickHelpWindow(this);
+       }
+      mHelpWindow->CenterOnParent();
+      mHelpWindow->ShowModal();
+      */
+    }
+    //====================================================================
 
 
 
@@ -2596,17 +2930,14 @@ namespace creaImageIO
          //================================================================
          //================================================================
          WxGimmickFrame::WxGimmickFrame( wxWindow *parent, 
-                                                                     wxString title, 
-                                                                     wxSize size)
+                                         wxString title, 
+                                         wxSize size)
            : wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size)
            {   
              wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
-             long style = wxTR_DEFAULT_STYLE |
-#ifndef NO_VARIABLE_HEIGHT
-               wxTR_HAS_VARIABLE_ROW_HEIGHT |
-#endif
-               wxTR_EDIT_LABELS | wxSUNKEN_BORDER;
-             mWxGimmick = new WxGimmick(this,-1,wxDefaultPosition,wxDefaultSize,style);
+             mWxGimmick = new WxGimmick(this,-1,
+                                        wxDefaultPosition,
+                                        wxDefaultSize);
              sizer->Add(mWxGimmick,1,wxGROW);
              SetSizer(sizer);
              SetAutoLayout(true);
@@ -2665,38 +2996,7 @@ namespace creaImageIO
 
 
 
-             //================================================================
-             //================================================================
-             //================================================================
-             //================================================================
-
-             //================================================================
-             WxGimmickSettingsDialog::WxGimmickSettingsDialog(wxWindow *parent)
-             : 
-             wxDialog( parent, 
-                       -1, 
-                       _T("Settings"),
-                       wxDefaultPosition,
-                       wxSize(400,400),
-                       wxRESIZE_BORDER | 
-                       wxSYSTEM_MENU  |
-                       wxCLOSE_BOX |
-                       wxMAXIMIZE_BOX | 
-                       wxMINIMIZE_BOX | 
-                       wxCAPTION  
-                       )
-             {
-             } 
-             //================================================================
-    
-             //================================================================
-             WxGimmickSettingsDialog::~WxGimmickSettingsDialog()
-               {
-               }
-             //================================================================
-
-    
-
+