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