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