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