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