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