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