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