]> Creatis software - creaImageIO.git/blob - src2/creaImageIOWxTreeView.cpp
03c5b0d3d3dab15af21147d39eab9ca01d53d01d
[creaImageIO.git] / src2 / creaImageIOWxTreeView.cpp
1 #include <creaImageIOWxTreeView.h>
2 #include <creaImageIOGimmickView.h>
3 #include <creaImageIOSystem.h>
4 #include <wx/splitter.h>
5 #include <wx/gdicmn.h>
6 #include <boost/date_time/gregorian/gregorian.hpp>
7
8 //=====================================================================
9 namespace creaImageIO
10 {
11
12   //=====================================================================
13 }
14 //=====================================================================
15
16 //=====================================================================
17 ///Comparing function for ordering algorithm. Takes parameters as strings.
18 int wxCALLBACK CompareFunctionStrings(long item1, long item2, long sortData)
19 {       
20   creaImageIO::ItemData* data1 = (creaImageIO::ItemData*)item1;
21   creaImageIO::ItemData* data2 = (creaImageIO::ItemData*)item2;
22
23   const std::string& s1(*(data1->attr));
24   const std::string& s2(*(data2->attr));
25   if(sortData==1)
26     {
27       // inverse the order
28       if (s1 < s2)
29         return 1;
30       if (s1 > s2)
31         return -1;
32       
33       return 0;
34     }
35   else
36     {
37       if (s1 < s2)
38         return -1;
39       if (s1 > s2)
40         return 1;
41       
42       return 0;
43       
44     }
45 }
46 //=====================================================================
47
48 //=====================================================================
49 ///Comparing function for ordering algorithm. Takes parameters as ints.
50 int wxCALLBACK CompareFunctionInts(long item1, long item2, long sortData)
51 {       
52   creaImageIO::ItemData* data1 = (creaImageIO::ItemData*)item1;
53   creaImageIO::ItemData* data2 = (creaImageIO::ItemData*)item2;
54
55   const std::string& s1(*(data1->attr));
56   const std::string& s2(*(data2->attr));
57
58   int val1=atoi(s1.c_str());
59   int val2=atoi(s2.c_str());
60
61   if(sortData==1)
62     {
63       // inverse the order
64       if (val1 < val2)
65         return 1;
66       if (val1 > val2)
67         return -1;
68       
69       return 0;
70     }
71   else
72     {
73       if (val1 < val2)
74         return -1;
75       if (val1 > val2)
76         return 1;
77
78       return 0;
79       
80     }
81   
82 }
83
84 //=====================================================================
85
86
87 //=====================================================================
88 namespace creaImageIO
89 {
90   //=====================================================================
91   // CTor
92   WxTreeView::WxTreeView(TreeHandler* handler,
93                          GimmickView* gimmick,
94                          wxWindow* parent,
95                          const wxWindowID id)
96     : wxPanel(parent,id),
97       TreeView(handler, gimmick)
98   {
99     GimmickDebugMessage(1,"WxTreeView::WxTreeView"
100                         <<std::endl);
101
102     
103     // Split part below toolbar into notebook for views and panel
104     // for preview, messages...
105     // TO DO : Splitter
106     //    mSplitter = new wxSplitterWindow( this , -1);
107
108     // Global sizer
109     wxBoxSizer  *sizer = new wxBoxSizer(wxHORIZONTAL);
110     
111     int ctrl_style = wxLC_REPORT | wxLC_VRULES;
112     int col_style = wxLIST_FORMAT_LEFT;
113
114     // Creating the ListCtrl for the levels > 0 (not for Root level)
115     for (int i = 0;
116          i < handler->GetTree().GetNumberOfLevels() -1;
117          ++i)
118       {
119         GimmickDebugMessage(5,"Creating view for level "<<i
120                             <<std::endl);
121         LevelType level;
122         level.SelectedUpToDate = true;
123         level.SortColumn = 0;
124
125         // If the first level : parent = this
126         wxWindow* sparent = this;
127         // else parent = last splitter
128         if (i>0) 
129                 sparent = mLevelList[i-1].wxSplitter;
130
131         level.wxSplitter = new wxSplitterWindow( sparent , -1);
132         if(i!=0)
133         {
134         level.wxSplitter->Show(false);
135         }
136         //          level.wxSplitter->SetMinimumPaneSize(100);
137         
138         wxListCtrl* ctrl = new wxListCtrl(level.wxSplitter,
139                                           i,
140                                           wxDefaultPosition, 
141                                           wxDefaultSize,
142                                           ctrl_style);
143         level.wxCtrl = ctrl;
144         level.wxSplitter->Initialize(ctrl);
145    
146         // Create the columns : one for each attribute of the level
147         int col = 0;
148         std::string title;
149
150         tree::LevelDescriptor::AttributeDescriptorListType::const_iterator a;
151         for (a  = handler->GetTree().GetAttributeDescriptorList(i+1).begin();
152              a != handler->GetTree().GetAttributeDescriptorList(i+1).end();
153              ++a)
154
155 {
156         
157             GimmickDebugMessage(5,"Creating column "<<col<<" : "
158                                 <<a->GetName()
159                                 <<std::endl);
160             
161             if(a->GetFlags()!=creaImageIO::tree::AttributeDescriptor::PRIVATE)
162               {
163                 
164                 if(a->GetName()=="UNKNOWN")
165                   {
166                     title = "#";
167                     title += handler->GetTree().GetLevelDescriptor(i+1).GetName();
168                     if (title[title.size()-1]!='s')
169                       title += "s";
170                     
171                   }
172                 else
173                   {
174                     title=a->GetName();
175                   }
176                   std::string temp = a->GetKey();
177                   if (temp.compare("ID") != 0)
178                   {
179                 
180                 ctrl->InsertColumn(col, 
181                                    crea::std2wx(title),
182                                    col_style);
183                 col++;
184                   }
185                 level.key.push_back(a->GetKey());
186               }
187                 
188           }
189           
190         mLevelList.push_back(level);
191       }
192     
193 #if wxUSE_MENUS
194
195          // Column Menu
196     menu =new wxMenu;
197         wxMenuItem* m1=menu->Append(wxID_ANY, _T("&Sort ascending"));
198         wxMenuItem* m2=menu->Append(wxID_ANY, _T("&Sort descending"));
199         wxMenuItem* m3=menu->Append(wxID_ANY, _T("&Filter"));
200         mAscendingID=m1->GetId();
201         mDescendingID=m2->GetId();
202         mFilterID=m3->GetId();
203         Connect( mAscendingID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WxTreeView::OnPopupSort) );
204         Connect( mDescendingID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WxTreeView::OnPopupSort) );
205         Connect( mFilterID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WxTreeView::OnPopupFilter) );
206
207
208
209         //ItemMenu
210         menuItem =new wxMenu;
211         wxMenuItem* m1Item=menuItem->Append(wxID_ANY, _T("&Anonymize"));
212         wxMenuItem* m2Item=menuItem->Append(wxID_ANY, _T("&Local Copy"));
213         wxMenuItem* m3Item=menuItem->Append(wxID_ANY, _T("&Edit Fields"));
214         
215         mAnonymizingID=m1Item->GetId();
216         mLocalCopyID=m2Item->GetId();
217         mEditFieldID=m3Item->GetId();
218         //Connect( mAnonymizingID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WxTreeView::OnAnonymize) );
219         Connect( mLocalCopyID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WxTreeView::OnLocalCopy) );
220         Connect( mEditFieldID, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(WxTreeView::OnEditField) );
221         
222         
223 #endif // wxUSE_MENUS
224         /// Initialize the first level splitter
225           
226         sizer->Add( mLevelList[0].wxSplitter ,1, wxGROW  ,0);
227         //      mColumnSelected=1;
228         mLastSelected=0;
229         mLastLevel=0;
230         //      mDirection=true;
231
232         mIgnoreSelectedChanged = false;
233
234         //CreateColorPalette();
235     UpdateLevel(1);
236
237     SetSizer( sizer );     
238     SetAutoLayout(true);
239     Layout();
240
241   }
242   //=====================================================================
243
244   //=====================================================================
245   /// Destructor
246   WxTreeView::~WxTreeView()
247   {
248     GimmickDebugMessage(1,"WxTreeView::~WxTreeView"
249                         <<std::endl);
250         delete menu;
251         delete menuItem;
252
253   }
254   //=====================================================================
255   
256   
257   
258   //=====================================================================
259   const std::vector<tree::Node*>& WxTreeView::GetSelected(int level)
260   {
261           std::vector<tree::Node*>& sel = mLevelList[0].Selected;
262     //  if (GetSelectedUpToDate(level)) 
263     int l = level - 1;
264     // the selection of upper level
265         if(mLevelList.size() == level -1)
266                  sel = mLevelList.back().Selected;
267         else
268                   sel=  mLevelList[l].Selected;
269         if (sel.size() > 0)
270         {
271                 sel.clear();
272         }
273           if (level == 1) 
274       {
275         sel.push_back(GetTreeHandler()->GetTree().GetTree());
276       }
277           else if (level < mLevelList.size()+2 ) 
278     {
279                 long item = -1;
280                 for ( ;; )
281                 {
282                         item = GetCtrl(l-1)->GetNextItem(item,
283                                                                                  wxLIST_NEXT_ALL,
284                                                                                  wxLIST_STATE_SELECTED);
285                         if ( item == -1 )
286                                 break;
287                         long adr = GetCtrl(l-1)->GetItemData(item);
288                         tree::Node* n = ((ItemData*)adr)->node;
289                         if(mLastSelected==item)
290                         {
291                                 std::vector<tree::Node*>::iterator it;
292                                 it = sel.begin();
293                                 it = sel.insert ( it , n );
294                         }
295                         else
296                         {
297                                 
298                                 sel.push_back(n);
299                         }                       
300                         
301                 }
302                 /*int n = GetCtrl(l-1)->GetItemCount();
303                 for (int i = 0; i<n; i++)
304                 {
305                         std::cout<<GetCtrl(l-1)->GetItemState(i,wxLIST_STATE_SELECTED)<<std::endl;
306                         if ( GetCtrl(l-1)->GetItemState(i,wxLIST_STATE_SELECTED))
307                         {
308                                 long adr = GetCtrl(l-1)->GetItemData(i);
309                                 tree::Node* n = ((ItemData*)adr)->node;
310                                 if(mLastSelected==i)
311                                 {
312                                         std::vector<tree::Node*>::iterator it;
313                                         it = sel.begin();
314                                         it = sel.insert ( it , n );
315                                 }
316                                 else
317                                 {
318                                         
319                                         sel.push_back(n);
320                                 }
321                         }
322               }*/
323           }
324         else
325         {
326                 // NOTHING
327         }   
328          
329     //    return mLevelList[level-1].Selected;
330     return sel;
331   }
332
333   //=====================================================================
334   
335   //=====================================================================
336   ///Removes selected nodes on last selected level
337    // NOT SPECIFIC 
338   void WxTreeView::RemoveSelected(std::string &i_save)
339   {
340          bool erase=false;
341          
342          unsigned int tempLevel = mLastLevel;
343     mLastLevel+=1;
344     const std::vector<tree::Node*>& sel=GetSelected(mLastLevel+1);
345         // if no selection, no remove action.
346     if(sel.size() != 0)
347         {
348         
349             std::stringstream out;
350             std::string levelName=GetTreeHandler()->GetTree().GetLevelDescriptor(mLastLevel).GetName();
351             out<<"Delete ";
352             out<<sel.size();
353             if(sel.size()>1&&levelName.at(levelName.size()-1)!='s')
354               {
355                 out<<" "<<levelName;
356                 out<<"s?";
357               }
358             else
359               {
360                 out<<" "<<GetTreeHandler()->GetTree().GetLevelDescriptor(mLastLevel).GetName()<<"?";
361               }
362             if (wxMessageBox(crea::std2wx(out.str()),
363                              _T("Remove Files"),
364                              wxYES_NO,this ) == wxYES)
365               {
366                 erase = true;
367               }
368             if(erase)
369                   {
370             GetGimmickView()->modifyValidationSignal(false);
371                     bool needRefresh=false;
372                     std::vector<tree::Node*>::const_iterator i;
373                     for (i=sel.begin(); i!=sel.end(); ++i)
374                       {
375                         GimmickMessage(1,
376                                        "deleting '"
377                                        <<(*i)->GetLabel()
378                                        <<"'"<<mLastLevel
379                                        <<std::endl);
380                         if((*i)->GetParent()->GetNumberOfChildren()<2)
381                           {
382                             needRefresh=true;
383                           }
384                           //tree::Node* n = new (tree::Node*)(*i);
385                           GetTreeHandler()->LoadChildren((*i),4);
386                           GetGimmickView()->AddIgnoreFile(*i);
387                           GetTreeHandler()->Remove(*i);
388                       }
389                     
390                     if(needRefresh && mLastLevel>1)
391                       {
392                         UpdateLevel(mLastLevel-2);
393                       }
394                     else if(mLastLevel>1)
395                       {
396                         UpdateLevel(mLastLevel-1);
397                       }
398                     else
399                       {
400                         UpdateLevel(mLastLevel);
401                       }
402                   }
403         }
404         else
405         {
406                 // no need to incremente level
407                 mLastLevel = tempLevel;
408         }
409     
410         if (erase && mLastLevel == 1 && i_save == "0")
411         {
412         
413                 RemoveAlertDlg *dial = new RemoveAlertDlg(this,  crea::std2wx("Remove files"), wxSize(370,100));
414                 //dial->ShowModal();
415                 if (dial->ShowModal() == wxID_OK)
416                 {
417                         i_save = dial->isChecked() == false? "0" : "1";
418                 }
419                 
420         }
421   }
422   
423   
424   //=====================================================================
425   /// Updates a level of the view (adds or removes children, etc.)
426   void WxTreeView::UpdateLevel( int level )
427   {
428     GimmickDebugMessage(1,
429                         GetTreeHandler()->GetTree().GetLabel()
430                         <<"WxTreeView::UpdateLevel(level "
431                         <<level
432                         <<")"
433                         <<std::endl);
434     
435     wxBusyCursor busy;
436     RecursiveUpdateLevel(level);
437     int i;
438     for (i=0; i<level-1; i++)
439       {
440         if (!GetSplitter(i)->IsSplit()) 
441           GetSplitter(i)->SplitVertically(  GetCtrl(i), GetSplitter(i+1),
442                                             100 );
443       }
444     if (GetSplitter(i)->IsSplit()) GetSplitter(i)->Unsplit();    
445     
446   }
447   //=====================================================================
448   
449   //=====================================================================
450   /// Recursive method called upon by UpdateLevel to refresh all windows
451   void WxTreeView::RecursiveUpdateLevel( int level )
452   {
453     GimmickDebugMessage(1,
454                         GetTreeHandler()->GetTree().GetLabel()
455                         <<"WxTreeView::RecursiveUpdateLevel(level "
456                         <<level
457                         <<")"<<std::endl);
458     
459     
460     const std::vector<tree::Node*>& sel(GetSelected(level));
461     
462     int l = level - 1;
463     
464     // to speed up inserting we hide the control temporarily
465     GetCtrl(l)->Hide();
466     GetCtrl(l)->DeleteAllItems();
467     
468     std::vector<tree::Node*>::const_iterator i;
469     
470     for (i=sel.begin(); i!=sel.end(); ++i)
471       {
472         GimmickDebugMessage(1,
473                             "adding children of '"
474                             <<(*i)->GetLabel()
475                             <<"'"
476                             <<std::endl);
477         int _id=0;
478         
479         //Adds items and sets their attributes 
480         
481         GetTreeHandler()->LoadChildren(*i,1);
482         tree::Node::ChildrenListType::reverse_iterator j;
483         for (j = (*i)->GetChildrenList().rbegin(); 
484              j!= (*i)->GetChildrenList().rend(); 
485              ++j)
486           {
487             GimmickDebugMessage(1,
488                                 "adding children "
489                                 <<(*j)->GetLabel()
490                                 <<"'"
491                                 <<std::endl);
492             
493             wxListItem item;
494             item.SetMask(wxLIST_MASK_STATE | 
495                          wxLIST_MASK_TEXT |
496                          //                      wxLIST_MASK_IMAGE |
497                          wxLIST_MASK_DATA |
498                          //                      wxLIST_MASK_WIDTH |
499                          wxLIST_MASK_FORMAT
500                          );
501             
502                 ItemData* data = new ItemData();
503             data->node = *j;
504             data->id = _id;
505                 
506             item.SetId(_id);
507             item.SetData(data);
508
509             _id++;
510             GetCtrl(l)->InsertItem(item);
511             
512             //Setting attributes
513             for (int k=0; k<GetCtrl(l)->GetColumnCount(); ++k)                          
514               {
515                 std::string val;
516                 //  Temporary correction : it works but no explanation about the problem FCY
517                 
518                 if(k==0 && level <3)
519                 {
520                   val = (*j)->GetAttribute("NumberOfChildren");
521                 }
522                 else
523                   val = (*j)->GetAttribute(mLevelList[l].key[k]);
524                 if(((*j)->GetAttributeDescriptor(mLevelList[l].key[k])).isDateEntry()) // Date
525                   {
526                     //                                    std::cout << "["<<val<< "]" << std::endl;
527                     std::string valtmp(val);
528                     try
529                       {
530                         boost::gregorian::date d1(boost::gregorian::from_undelimited_string(val));                                 
531                         val = to_iso_extended_string(d1);
532                       }
533                     catch (...)
534                       {
535                         val =  valtmp;
536                       }
537                     //                                    std::cout << "["<<val<< "]" << std::endl;     
538                   }
539                 else if(((*j)->GetAttributeDescriptor(mLevelList[l].key[k])).isTimeEntry()) // Time
540                   {
541                     if ((val.size()>6) && 
542                         (val != "" || val != " "))
543                       val = val.substr(0,2) + " : " 
544                         + val.substr(2,2) + " : " 
545                         + val.substr(4,2);
546                   }
547                 else
548                   {
549                     if (val.size()==0) val = "?";
550                   }
551                 if (val.size()==0) val = "X";
552                 item.SetText( crea::std2wx(val));
553                 item.SetColumn(k);
554                   
555                   GetCtrl(l)->SetItem(item);
556                   }
557                 item.Clear();
558             
559           }
560       }
561     
562     SortLevel(l);
563     GetCtrl(l)->Show();
564   }
565   //=====================================================================
566   
567   
568   //================================================================
569   void WxTreeView::OnItemDeSelected(wxListEvent& event)
570   { 
571     GimmickDebugMessage(1,
572                         GetTreeHandler()->GetTree().GetLabel()
573                         <<" WxTreeView::OnItemDeselected"<<std::endl);
574     // retrieve the level
575     wxObject* obj = event.GetEventObject();   
576     unsigned int level = 0;
577     for (level = 0; level<mLevelList.size(); ++level)
578       {
579         if ( GetCtrl(level) == obj ) break;
580       } 
581     SetSelectedUpToDate(level,false);
582     // to allow a first selection in images TreeView
583     if (level==mLevelList.size()-1) 
584       OnItemSelected(event);
585   }
586   //================================================================
587   
588   //================================================================
589   void WxTreeView::OnItemSelected(wxListEvent& event)
590   { 
591           
592     GimmickDebugMessage(1,
593                         GetTreeHandler()->GetTree().GetLabel()
594                         <<" WxTreeView::OnItemSelected"<<std::endl);
595
596     if (mIgnoreSelectedChanged) 
597       {
598         GimmickDebugMessage(1,
599                             " mIgnoreSelectedChanged true: returning"
600                             <<std::endl);
601         return;
602       }
603     
604
605     
606     wxListItem info;
607     info.m_itemId = event.m_itemIndex;
608     mLastSelected = event.m_itemIndex;
609     // retrieve the level
610     wxObject* obj = event.GetEventObject();   
611     unsigned int level = 0;
612     for (level = 0; level<mLevelList.size(); ++level)
613       {
614         if ( GetCtrl(level) == obj ) break;
615       }
616         mLastLevel=level;
617     GimmickDebugMessage(1,
618                         " Level "<<level+1
619                         <<std::endl);
620     
621     // Update the children level (if selection not at last level)
622     if (level<mLevelList.size()-1) 
623       {
624                 
625         UpdateLevel( level + 2 ); 
626         // Reset the viewer setting the default image
627         GetGimmickView()->ClearSelection();
628       }
629     // Select all images if the selection is at series level
630     if (level==mLevelList.size()-2) 
631                 SelectAll(level+1);
632     // Validate selected images if the selection is at image level
633     if (level==(mLevelList.size()-1)) //&&mProcess) 
634       {
635         if(event.GetEventType()==wxEVT_COMMAND_LIST_ITEM_SELECTED)
636           {
637                   ValidateSelectedImages (true);
638           }
639         else
640           {
641                   ValidateSelectedImages (false);
642           }
643       }
644     
645   }
646   //================================================================
647
648   //================================================================
649   void WxTreeView::SelectAll(int level)
650   {
651     long item = -1;
652     //    int level=mLevelList.size()-1;
653     for ( ;; )
654       {
655         item = GetCtrl(level)->GetNextItem(item,
656                                            wxLIST_NEXT_ALL);
657         if ( item == -1 )
658           break;
659         
660         if(item==(GetCtrl(level)->GetItemCount()-1))
661           {
662             mIgnoreSelectedChanged = false;//mProcess=true;
663           }
664         else
665           {
666             mIgnoreSelectedChanged = true;//    mProcess=false;
667           }
668         GetCtrl(level)->SetItemState(item,wxLIST_STATE_SELECTED, wxLIST_MASK_STATE 
669                                      | wxLIST_MASK_TEXT |wxLIST_MASK_IMAGE | wxLIST_MASK_DATA | wxLIST_MASK_WIDTH | wxLIST_MASK_FORMAT);
670       }
671   }
672
673   //================================================================
674   //================================================================
675
676   void WxTreeView::OnColClick(wxListEvent& event)
677   { 
678     mColumnSelected = event.m_col;
679     wxPoint clientpt;
680     clientpt.x = wxGetMousePosition().x - this->GetScreenPosition().x;
681     clientpt.y = wxGetMousePosition().y - this->GetScreenPosition().y;
682     senderCtrl = event.GetEventObject(); 
683     unsigned int level = 0;
684     for (level = 0; level<mLevelList.size(); ++level)
685       {
686         if ( GetCtrl(level) == senderCtrl ) break;
687       }
688     PopupMenu(menu, clientpt);
689     
690   }
691
692    //================================================================
693   //================================================================
694
695   void WxTreeView::OnItemMenu(wxListEvent &event)
696   {
697          wxPoint clientpt;
698     clientpt.x = wxGetMousePosition().x - this->GetScreenPosition().x;
699     clientpt.y = wxGetMousePosition().y - this->GetScreenPosition().y;
700     senderCtrl = event.GetEventObject();
701     unsigned int level = 0;
702     for (level = 0; level<mLevelList.size(); ++level)
703       {
704                 if ( GetCtrl(level) == senderCtrl ) break;
705       }
706           long* ptr=0;
707           int flag;
708           mLastRightLevel=level;
709           mLastRightSelected=GetCtrl(level)->HitTest(wxPoint(0,clientpt.y-8),flag,ptr);
710     PopupMenu(menuItem, clientpt);
711     
712   }
713   
714   //================================================================
715   //================================================================
716
717   void WxTreeView::OnPopupFilter(wxCommandEvent& event)
718   {
719     wxBusyCursor busy;
720     GimmickDebugMessage(7,
721                         "WxTreeView::OnEndLabelEdit" 
722                         <<std::endl);
723     unsigned int level = 0;
724     for (level = 0; level<mLevelList.size(); ++level)
725       {
726         if ( GetCtrl(level) == senderCtrl ) break;
727       }
728     std::string filter = crea::wx2std(wxGetTextFromUser(_T("Enter the filter to apply"), _T("Filter On Column")));
729     
730     std::string att;
731     
732     long it = -1;
733     UpdateLevel(level+1);
734     
735     std::vector<long> items;
736     bool in=false;
737     int del=0;
738     for ( ;; )
739       {
740         it = GetCtrl(level)->GetNextItem(it,
741                                          wxLIST_NEXT_ALL);
742         if ( it == -1 )
743           break;
744         
745         long adr = GetCtrl(level)->GetItemData(it);
746         tree::Node* nod = ((ItemData*)adr)->node;
747         att=(*nod).GetAttribute(mLevelList[level].key[mColumnSelected]);
748         
749         
750         if(att.find(filter)>900)
751           {
752             
753             if(!in)
754               {
755                 in=true;
756               }
757             else
758               {
759                 del+=1;
760               }
761             
762             items.push_back(it-del);
763           }
764         
765       }
766     std::vector<long>::iterator iter;
767     for(iter=items.begin();iter!=items.end();++iter)
768       {
769         GetCtrl(level)->DeleteItem(*iter);
770       }
771     GetGimmickView()->ClearSelection();
772   }
773   //================================================================
774   
775   //================================================================
776   void WxTreeView::OnPopupSort(wxCommandEvent& event)
777   {
778     wxBusyCursor busy;
779     unsigned int level = 0;
780     for (level = 0; level<mLevelList.size(); ++level)
781       {
782         if ( GetCtrl(level) == senderCtrl ) break;
783       }
784     mLevelList[level].SortColumn = mColumnSelected;
785
786     if(event.GetId()==mAscendingID)
787       {
788         mLevelList[level].SortAscending = true;
789       }
790     else if(event.GetId()==mDescendingID)
791       {
792         mLevelList[level].SortAscending = false;
793       }
794           
795     SortLevel(level);
796   }
797   //================================================================
798
799   //================================================================
800   void WxTreeView::OnLocalCopy(wxCommandEvent& event)
801   {
802     wxBusyCursor busy;
803     
804         unsigned int tempLevel = mLastLevel;
805     mLastLevel+=1;
806     const std::vector<tree::Node*>& sel=GetSelected(mLastLevel+1);
807         
808     if(sel.size() != 0)
809         {
810             bool copy=false;
811             std::stringstream out;
812             std::string levelName=GetTreeHandler()->GetTree().GetLevelDescriptor(mLastLevel).GetName();
813             out<<"Copy ";
814             out<<sel.size();
815             if(sel.size()>1&&levelName.at(levelName.size()-1)!='s')
816               {
817                 out<<" "<<levelName;
818                 out<<"s to .gimmick?";
819               }
820             else
821               {
822                 out<<" "<<GetTreeHandler()->GetTree().GetLevelDescriptor(mLastLevel).GetName()<<" to .gimmick?";
823               }
824             if (wxMessageBox(crea::std2wx(out.str()),
825                              _T("Remove Files"),
826                              wxYES_NO,this ) == wxYES)
827               {
828                 copy = true;
829               }
830             if(copy)
831                   {
832                         std::vector<std::string> s;
833                         GetFilenamesAsString(sel,s);
834             GetGimmickView()->CopyFiles(s);
835                   }
836         }
837         else
838         {
839                 mLastLevel = tempLevel;
840         }
841     
842     
843   }
844   //================================================================
845
846    //================================================================
847   void WxTreeView::OnEditField(wxCommandEvent& event)
848   {
849         if(mLastRightSelected!=-1)
850         {
851     tree::Node* node=((ItemData*)GetCtrl(mLastRightLevel)->GetItemData(mLastRightSelected))->node;
852         tree::LevelDescriptor::AttributeDescriptorListType::const_iterator a;
853         std::vector<std::string> names;
854         std::vector<std::string> keys;
855         for (a  = GetTreeHandler()->GetTree().GetAttributeDescriptorList(mLastRightLevel+1).begin();
856              a != GetTreeHandler()->GetTree().GetAttributeDescriptorList(mLastRightLevel+1).end();
857              ++a)
858         {
859                 if(a->GetFlags()==creaImageIO::tree::AttributeDescriptor::EDITABLE)
860             {
861                         names.push_back(a->GetName());
862                         keys.push_back(a->GetKey());
863                 }
864         }
865         GetGimmickView()->CreateEditFieldsDialog(node,names,keys);
866         }
867   }
868   //================================================================
869
870   //================================================================
871   void WxTreeView::SortLevel(int level)
872   {       
873     GimmickDebugMessage(1,
874                         "WxTreeView::SortLevel(" 
875                         <<level<<")"
876                         <<std::endl);  
877     //Obtain the column name and the level that needs to be organized
878     
879     //    int l = level - 1;
880     //Sets the data for the items to be sorted
881     //    std::string att;
882     unsigned int ty=0;
883     int nbselected = 0;
884     int n = GetCtrl(level)->GetItemCount();
885     for (int i = 0; i < n; i++)
886       {
887         
888         //Gets current item data
889         ItemData* data = (ItemData*)GetCtrl(level)->GetItemData(i);
890         
891         //Extracts the node and the type of attribute   
892         tree::Node* nod = data->node;
893         if(i==0)
894           {
895             (*nod).GetAttributeDescriptor
896               (mLevelList[level].key[mLevelList[level].SortColumn])
897               .DecodeType( ty );
898           }
899         //Obtains the organizing attribute
900         data->attr = & (*nod).GetAttribute
901           (mLevelList[level].key[mLevelList[level].SortColumn]);
902         //Selected ?
903         data->selected = false;
904         if (GetCtrl(level)->GetItemState(i,wxLIST_STATE_SELECTED)>0)
905           {
906             data->selected = true;
907             nbselected++;
908           }
909
910       } 
911     GimmickDebugMessage(1,
912                         "WxTreeView::OnSort : " 
913                         <<nbselected<<" selected before sorting"
914                         <<std::endl);  
915
916     mIgnoreSelectedChanged = true; 
917     // 
918     if (mLevelList[level].SortAscending)
919       {
920         
921         if(ty==1)
922           {
923             GetCtrl(level)->SortItems(CompareFunctionInts, 0);
924           }
925         else
926           {
927             GetCtrl(level)->SortItems(CompareFunctionStrings, 0);
928           }
929         
930       }
931     else
932       {
933         if(ty==1)
934           {
935             GetCtrl(level)->SortItems(CompareFunctionInts, 1);
936           }
937         else
938           {
939             GetCtrl(level)->SortItems(CompareFunctionStrings, 1);
940           }
941       }
942  
943
944     // Reselects the unselected 
945     n = GetCtrl(level)->GetItemCount();
946     int after = 0;
947     for (int i = 0; i < n; i++)
948       {
949         
950         //Gets current item data
951         ItemData* data = (ItemData*)GetCtrl(level)->GetItemData(i);
952   
953         //  long item = -1;
954         //    for ( ;; )
955         //      {
956         //      item = GetCtrl(level)->GetNextItem(item,wxLIST_NEXT_ALL);
957         //      if ( item == -1 ) break;
958         //Gets current item data
959         //      ItemData* data = (ItemData*)GetCtrl(level)->GetItemData(item);
960         // was selected ?
961         
962         if (data->selected)
963           {
964             nbselected--;
965             if (nbselected==0)
966               {
967                 // if it is the last one we must process the selection
968                 mIgnoreSelectedChanged = false;
969               }
970             GetCtrl(level)->SetItemState(i,
971                                          wxLIST_STATE_SELECTED, 
972                                          wxLIST_MASK_STATE 
973                                          | wxLIST_MASK_TEXT 
974                                          | wxLIST_MASK_IMAGE 
975                                          | wxLIST_MASK_DATA 
976                                          | wxLIST_MASK_WIDTH 
977                                          | wxLIST_MASK_FORMAT);   
978           }
979         if (GetCtrl(level)->GetItemState(i,wxLIST_STATE_SELECTED)>0)
980           {
981             after++;
982           }
983
984         
985       }
986     mIgnoreSelectedChanged = false; 
987      GimmickDebugMessage(1,
988                         "WxTreeView::SortLevel : " 
989                         <<after<<" selected after sorting"
990                         <<std::endl);  
991   
992   }
993   //================================================================
994
995   
996   //================================================================
997   void WxTreeView::ValidateSelectedImages(bool isSelection)
998   {
999     GimmickDebugMessage(7,
1000                         "WxTreeView::ValidateSelectedImages" 
1001                         <<std::endl);
1002     const std::vector<tree::Node*>& sel(GetSelected(mLevelList.size()+1));
1003     GetGimmickView()->OnSelectionChange(sel,
1004                                         isSelection,(mLastSelected-1),
1005                                         !mIgnoreSelectedChanged);
1006  
1007   }
1008   //================================================================
1009
1010
1011   //================================================================
1012   void WxTreeView::GetNodes(std::vector<tree::Node*>& nodes, bool direction)
1013   {
1014         long item = mLastSelected;
1015         int level=mLevelList.size()-1;
1016         //Gets current item data
1017         long adr = GetCtrl(level)->GetItemData(item);
1018         //Extracts the node
1019         tree::Node* nod = ((ItemData*)adr)->node;
1020     for ( ;; )
1021     {
1022                 if(direction)
1023                 {
1024                         item = GetCtrl(level)->GetNextItem(item,
1025                                      wxLIST_NEXT_ABOVE);
1026                 }
1027                 else
1028                 {
1029                         item = GetCtrl(level)->GetNextItem(item,
1030                                      wxLIST_NEXT_BELOW);
1031                 }
1032         if ( item == -1 || item==0  )
1033                 {
1034             break;
1035                 }
1036                 if(GetCtrl(level)->GetItemState(item, wxLIST_STATE_SELECTED)==0 )
1037                 {
1038
1039                         adr = GetCtrl(level)->GetItemData(item);
1040                         nod = ((ItemData*)adr)->node;
1041                         nodes.push_back(nod);
1042                 }
1043     }
1044
1045   }
1046   //================================================================
1047    //=================================================
1048   void WxTreeView::OnKeyDown(wxListEvent &event)
1049   {
1050           if(event.GetKeyCode() == WXK_DELETE)
1051           {
1052                    wxBusyCursor busy;
1053                    std::string temp = "0";
1054                    RemoveSelected(temp);
1055                    GetGimmickView()->ClearSelection();
1056           }
1057                   
1058   }
1059   //================================================================
1060
1061   //================================================================
1062   // Should be in another place : not specific !
1063   void WxTreeView::GetSelectedAsString(std::vector<std::string>&s)
1064   {
1065     int level=mLevelList.size();
1066     const std::vector<tree::Node*>& sel=GetSelected(level+1);
1067     std::vector<tree::Node*>::const_iterator i;
1068     
1069     for (i=sel.begin(); i!=sel.end(); ++i)
1070       {
1071         std::string filename=(*i)->GetAttribute("FullFileName");
1072         s.push_back(filename);
1073       }
1074   }
1075
1076   //================================================================
1077   void WxTreeView::GetFilenamesAsString(const std::vector<tree::Node*>& nodes, std::vector<std::string>&s)
1078   {
1079     std::vector<tree::Node*>::const_iterator i;
1080     
1081     for (i=nodes.begin(); i!=nodes.end(); ++i)
1082       {
1083                   if((*i)->GetLevel()<mLevelList.size())
1084                   {
1085                          GetTreeHandler()->LoadChildren(*i,0);
1086                          GetFilenamesAsString((*i)->GetChildrenList(),s);
1087                   }
1088                   else
1089                   {
1090                         std::string filename=(*i)->GetAttribute("FullFileName");
1091                         s.push_back(filename);
1092                   }
1093       }
1094   }
1095
1096    //================================================================
1097
1098    //================================================================
1099   void WxTreeView::GetAttributes(std::vector<std::string>& areShown, std::vector<std::string>& notShown, int level)
1100   {
1101           areShown.clear();
1102           notShown.clear();
1103         tree::LevelDescriptor::AttributeDescriptorListType::const_iterator a;
1104         for (a  = GetTreeHandler()->GetTree().GetAttributeDescriptorList(level).begin();
1105              a != GetTreeHandler()->GetTree().GetAttributeDescriptorList(level).end();
1106              ++a)
1107         {
1108                 if(a->GetFlags()==creaImageIO::tree::AttributeDescriptor::EDITABLE && IsAttributeVisible(a->GetName(),level))
1109             {
1110                         areShown.push_back(a->GetName());
1111                 }
1112         }
1113         notShown=mLevelList[level-1].notShownAtts;
1114   }
1115
1116   //================================================================
1117   void WxTreeView::SetNonVisibleAttributes(const std::vector<std::string>& notShown, int nlevel)
1118   {
1119         mLevelList[nlevel].notShownAtts=notShown;
1120   }
1121
1122   //================================================================
1123    void WxTreeView::CreateCtrl(std::vector<std::string>& notShown, int nlevel)
1124   {
1125         int ctrl_style = wxLC_REPORT | wxLC_VRULES;
1126     int col_style = wxLIST_FORMAT_LEFT;
1127         LevelType level;
1128         mLevelList[nlevel].SelectedUpToDate = true;
1129         mLevelList[nlevel].SortColumn = 0;
1130         mLevelList[nlevel].key.clear();
1131         
1132         mLevelList[nlevel].wxCtrl = new wxListCtrl(mLevelList[nlevel].wxSplitter,
1133                                           nlevel,
1134                                           wxDefaultPosition, 
1135                                           wxDefaultSize,
1136                                           ctrl_style);
1137         wxWindow* oldWin=mLevelList[nlevel].wxSplitter->GetWindow1();
1138         mLevelList[nlevel].wxSplitter->ReplaceWindow(oldWin,mLevelList[nlevel].wxCtrl);
1139         mLevelList[nlevel].wxSplitter->Initialize(mLevelList[nlevel].wxCtrl);
1140    
1141         // Create the columns : one for each attribute of the level
1142         int col = 0;
1143         std::string title;
1144
1145         tree::LevelDescriptor::AttributeDescriptorListType::const_iterator a;
1146         for (a  = GetTreeHandler()->GetTree().GetAttributeDescriptorList(nlevel+1).begin();
1147              a != GetTreeHandler()->GetTree().GetAttributeDescriptorList(nlevel+1).end();
1148              ++a)
1149
1150         {   
1151             if(a->GetFlags()!=creaImageIO::tree::AttributeDescriptor::PRIVATE && IsAttributeVisible(a->GetName(),nlevel+1))
1152               {
1153                   title=a->GetName();
1154                   std::string temp = a->GetKey();
1155                   if (temp.compare("ID") != 0)
1156                   {
1157                         mLevelList[nlevel].wxCtrl->InsertColumn(col, 
1158                                         crea::std2wx(title),
1159                                         col_style);
1160                         col++;
1161                   }
1162                 mLevelList[nlevel].key.push_back(a->GetKey());
1163               }
1164                 
1165           }
1166         oldWin->Destroy();
1167         UpdateLevel(1);
1168         }
1169
1170    //================================================================
1171   bool WxTreeView::IsAttributeVisible(const std::string& val, int level)
1172   {
1173           std::vector<std::string> ns=mLevelList[level-1].notShownAtts;
1174           std::vector<std::string>::iterator it;
1175           bool found=false;
1176           for(it=ns.begin();it!=ns.end()&&!found;++it)
1177           {
1178                   if(val.compare(*it)==0)
1179                   {
1180                           found=true;
1181                   }
1182           }
1183
1184           return !found;
1185   }
1186  //================================================================
1187   //================================================================
1188
1189         RemoveAlertDlg::RemoveAlertDlg(wxWindow *parent, 
1190                                                wxString title,    
1191                                                    const wxSize& size)
1192  :   wxDialog( parent, 
1193                   wxID_ANY, 
1194                   title,
1195                   wxDefaultPosition,
1196                   size,
1197                   wxDEFAULT_DIALOG_STYLE)
1198         {
1199             wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
1200
1201                 //std::string out("To reload deleted patient, you should synchronize your database before.");  // JPR
1202                 //wxTextCtrl *text = new wxTextCtrl(this, wxID_ANY,crea::std2wx(out),wxDefaultPosition, wxSize(500,20));
1203                 wxTextCtrl *text = new wxTextCtrl(this, wxID_ANY,
1204                                         _T("To reload deleted patient, you should synchronize your database before."),
1205                                         wxDefaultPosition, wxSize(500,20));
1206                 mcheck = new wxCheckBox(this, 5478, _T("Do not display this warning again!"));
1207                 Connect( mcheck->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED , (wxObjectEventFunction) &RemoveAlertDlg::onCheck ); 
1208                 wxSizer* buttonsSizer = this->CreateSeparatedButtonSizer(wxOK|wxCANCEL);
1209                 
1210                 topsizer->Add(text);
1211                 topsizer->Add(mcheck,0,wxGROW);
1212                 topsizer->Add(buttonsSizer,0,wxGROW);
1213                 SetSizer(topsizer, true);
1214                 mSave = false;
1215                 Layout();
1216         }
1217         RemoveAlertDlg::~RemoveAlertDlg(){};
1218         bool RemoveAlertDlg::isChecked()
1219         {
1220                 return mSave;
1221         }
1222         void RemoveAlertDlg::onCheck(wxCommandEvent &Event)
1223         {
1224                 mSave = mcheck->IsChecked();
1225         }
1226         
1227
1228   //================================================================
1229   //================================================================
1230   BEGIN_EVENT_TABLE(WxTreeView, wxPanel)   
1231   /*
1232     EVT_SIZE(MyFrame::OnSize)
1233
1234     EVT_MENU(LIST_QUIT, MyFrame::OnQuit)
1235     EVT_MENU(LIST_ABOUT, MyFrame::OnAbout)
1236     EVT_MENU(LIST_LIST_VIEW, MyFrame::OnListView)
1237     EVT_MENU(LIST_REPORT_VIEW, MyFrame::OnReportView)
1238     EVT_MENU(LIST_ICON_VIEW, MyFrame::OnIconView)
1239     EVT_MENU(LIST_ICON_TEXT_VIEW, MyFrame::OnIconTextView)
1240     EVT_MENU(LIST_SMALL_ICON_VIEW, MyFrame::OnSmallIconView)
1241     EVT_MENU(LIST_SMALL_ICON_TEXT_VIEW, MyFrame::OnSmallIconTextView)
1242     EVT_MENU(LIST_VIRTUAL_VIEW, MyFrame::OnVirtualView)
1243     EVT_MENU(LIST_SMALL_VIRTUAL_VIEW, MyFrame::OnSmallVirtualView)
1244
1245     EVT_MENU(LIST_FOCUS_LAST, MyFrame::OnFocusLast)
1246     EVT_MENU(LIST_TOGGLE_FIRST, MyFrame::OnToggleFirstSel)
1247     EVT_MENU(LIST_DESELECT_ALL, MyFrame::OnDeselectAll)
1248     EVT_MENU(LIST_SELECT_ALL, MyFrame::OnSelectAll)
1249     EVT_MENU(LIST_DELETE, MyFrame::OnDelete)
1250     EVT_MENU(LIST_ADD, MyFrame::OnAdd)
1251     EVT_MENU(LIST_EDIT, MyFrame::OnEdit)
1252     EVT_MENU(LIST_DELETE_ALL, MyFrame::OnDeleteAll)
1253     EVT_MENU(LIST_SORT, MyFrame::OnSort)
1254     EVT_MENU(LIST_SET_FG_COL, MyFrame::OnSetFgColour)
1255     EVT_MENU(LIST_SET_BG_COL, MyFrame::OnSetBgColour)
1256     EVT_MENU(LIST_TOGGLE_MULTI_SEL, MyFrame::OnToggleMultiSel)
1257     EVT_MENU(LIST_SHOW_COL_INFO, MyFrame::OnShowColInfo)
1258     EVT_MENU(LIST_SHOW_SEL_INFO, MyFrame::OnShowSelInfo)
1259     EVT_MENU(LIST_FREEZE, MyFrame::OnFreeze)
1260     EVT_MENU(LIST_THAW, MyFrame::OnThaw)
1261     EVT_MENU(LIST_TOGGLE_LINES, MyFrame::OnToggleLines)
1262     EVT_MENU(LIST_MAC_USE_GENERIC, MyFrame::OnToggleMacUseGeneric)
1263
1264     EVT_UPDATE_UI(LIST_SHOW_COL_INFO, MyFrame::OnUpdateShowColInfo)
1265     EVT_UPDATE_UI(LIST_TOGGLE_MULTI_SEL, MyFrame::OnUpdateToggleMultiSel)
1266 END_EVENT_TABLE()
1267
1268 BEGIN_EVENT_TABLE(MyListCtrl, wxListCtrl)
1269     EVT_LIST_BEGIN_DRAG(LIST_CTRL, MyListCtrl::OnBeginDrag)
1270     EVT_LIST_BEGIN_RDRAG(LIST_CTRL, MyListCtrl::OnBeginRDrag)
1271         
1272     EVT_LIST_BEGIN_LABEL_EDIT(-1, WxTreeView::OnBeginLabelEdit)
1273     EVT_LIST_END_LABEL_EDIT(-1, WxTreeView::OnEndLabelEdit)
1274         
1275     EVT_LIST_DELETE_ITEM(LIST_CTRL, MyListCtrl::OnDeleteItem)
1276     EVT_LIST_DELETE_ALL_ITEMS(LIST_CTRL, MyListCtrl::OnDeleteAllItems)
1277 #if WXWIN_COMPATIBILITY_2_4
1278     EVT_LIST_GET_INFO(LIST_CTRL, MyListCtrl::OnGetInfo)
1279     EVT_LIST_SET_INFO(LIST_CTRL, MyListCtrl::OnSetInfo)
1280 #endif
1281   */
1282     EVT_LIST_KEY_DOWN(-1, WxTreeView::OnKeyDown)
1283     EVT_LIST_ITEM_SELECTED(-1, WxTreeView::OnItemSelected)
1284         EVT_LIST_ITEM_RIGHT_CLICK(-1, WxTreeView::OnItemMenu)
1285     EVT_LIST_ITEM_DESELECTED(-1, WxTreeView::OnItemDeSelected)
1286         /*
1287     EVT_LIST_KEY_DOWN(LIST_CTRL, MyListCtrl::OnListKeyDown)
1288     EVT_LIST_ITEM_ACTIVATED(LIST_CTRL, MyListCtrl::OnActivated)
1289     EVT_LIST_ITEM_FOCUSED(LIST_CTRL, MyListCtrl::OnFocused)
1290 */
1291     EVT_LIST_COL_RIGHT_CLICK(-1, WxTreeView::OnColClick)
1292         
1293     EVT_LIST_COL_CLICK(-1, WxTreeView::OnColClick)
1294
1295         //EVT_LEFT_DOWN(WxTreeView::OnMouseClick)
1296         /*
1297     EVT_LIST_COL_BEGIN_DRAG(LIST_CTRL, MyListCtrl::OnColBeginDrag)
1298     EVT_LIST_COL_DRAGGING(LIST_CTRL, MyListCtrl::OnColDragging)
1299     EVT_LIST_COL_END_DRAG(LIST_CTRL, MyListCtrl::OnColEndDrag)
1300
1301     EVT_LIST_CACHE_HINT(LIST_CTRL, MyListCtrl::OnCacheHint)
1302
1303 #if USE_CONTEXT_MENU
1304     EVT_CONTEXT_MENU(MyListCtrl::OnContextMenu)
1305 #endif
1306     EVT_CHAR(MyListCtrl::OnChar)
1307
1308     EVT_RIGHT_DOWN(MyListCtrl::OnRightClick)
1309   */
1310 END_EVENT_TABLE()
1311   
1312 } // EO namespace creaImageIO
1313