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