2 #include <creaImageIOWxGimmick.h>
3 #include <creaImageIODicomNodeComparators.h>
5 #include <creaMessageManager.h>
7 #include "icons/database.xpm"
8 #include "icons/folder.xpm"
9 #include "icons/dicomdir.xpm"
10 #include "icons/patient.xpm"
11 #include "icons/study.xpm"
12 #include "icons/series.xpm"
13 #include "icons/image.xpm"
14 #include "icons/root.xpm"
15 #include <wx/filedlg.h>
16 #include <wx/dirdlg.h>
19 #include <vtkCamera.h>
20 #include <vtkRenderer.h>
22 #include <wx/filefn.h>
23 //#include <wx/tipwin.h>
27 #include <boost/filesystem.hpp>
28 #include <boost/algorithm/string.hpp>
32 //================================================================
33 const int WxGimmick::UserMenuFirstId = 1000;
34 //================================================================
36 //================================================================
49 //================================================================
51 //================================================================
54 PopUp_NewCollection = 100,
55 PopUp_OpenCollection = 101,
56 PopUp_CloseCollection = 102,
57 PopUp_DeleteCollection = 103,
58 PopUp_AddDirectory = 110,
60 PopUp_AddRawFile = 112,
65 PopUp_User = WxGimmick::UserMenuFirstId,
67 //================================================================
69 //================================================================
70 #define TreeListCtrlId 10000
71 //================================================================
73 //================================================================
74 const icon_id Icon[5] = { Icon_Database,
79 //================================================================
82 //================================================================
83 class WxGimmickDicomNodeData : public DicomNodeData
86 WxGimmickDicomNodeData
87 (WxGimmickTreeItemData* d = 0) :
91 ~WxGimmickDicomNodeData();
93 WxGimmickTreeItemData* GetTreeItemData()
94 { return mTreeItemData; }
95 void SetTreeItemData( WxGimmickTreeItemData* d)
96 { mTreeItemData = d; }
97 inline bool IsLoaded() { return mLoaded; }
98 inline void SetLoaded(bool v) { mLoaded = v; }
101 WxGimmickTreeItemData* mTreeItemData;
104 //================================================================
107 //================================================================
108 class WxGimmickTreeItemData : public wxTreeItemData
111 WxGimmickTreeItemData(DicomNode* node)
121 WxGimmickDicomNodeData* data =
122 node->GetData<WxGimmickDicomNodeData*>();
125 if (data->GetTreeItemData()!=0)
127 std::cout << "WxGimmickTreeItemData ERROR ****"
131 data->SetTreeItemData(this);
134 node->SetData( new WxGimmickDicomNodeData(this) );
135 if (node->GetType()==DicomNode::Database)
145 ~WxGimmickTreeItemData()
149 WxGimmickDicomNodeData* data =
150 mDicomNode->GetData<WxGimmickDicomNodeData*>();
151 if (data) data->SetTreeItemData(0);
155 inline void ResetDicomNode()
160 inline void SetItemId ( const wxTreeItemId& item ) { mItemId = item; }
161 inline const wxTreeItemId& GetItemId() const { return mItemId; }
163 inline bool IsDefault() const { return (mType == 0); }
164 inline bool IsDatabase() const { return (mType == 2); }
165 inline bool IsDicomNode() const { return (mType == 1); }
167 inline DicomNode* GetDicomNode() { return mDicomNode; }
168 inline long& UpdateTime() { return mUpdateTime; }
169 inline bool IsLoaded()
171 mDicomNode->GetData<WxGimmickDicomNodeData*>()->IsLoaded();
173 inline void SetLoaded(bool v)
175 mDicomNode->GetData<WxGimmickDicomNodeData*>()->SetLoaded(v);
178 inline int GetUserFlags() const { return mUserFlags; }
179 inline void SetUserFlags(int f) { mUserFlags = f; }
182 // The type of item :
185 // 2 = DicomNode of type Database
187 wxTreeItemId mItemId;
188 DicomNode* mDicomNode;
193 //================================================================
196 //================================================================
197 WxGimmickDicomNodeData::~WxGimmickDicomNodeData()
201 mTreeItemData->ResetDicomNode();
204 //================================================================
239 //================================================================
240 //================================================================
241 //================================================================
242 //================================================================
243 //================================================================
244 //================================================================
245 //================================================================
246 WxGimmick::WxGimmick(wxWindow *parent,
252 : wxPanel(parent,id,pos,size),
253 mSelectionType(image_type),
254 mSaveConfigurationOnClose(true),
257 // Initialize image size corresponding to current selection
258 switch (mSelectionType)
260 case GIMMICK_2D_IMAGE_SELECTION : mSelectionMaxImageDimension = 2; break;
261 case GIMMICK_3D_IMAGE_SELECTION : mSelectionMaxImageDimension = 3; break;
262 case GIMMICK_4D_IMAGE_SELECTION : mSelectionMaxImageDimension = 4; break;
263 default : mSelectionMaxImageDimension = 0;
267 // Start the threads ...
271 SetDatabaseExtension("sqlite3");
272 // Create the UserSettings dir if does not exist
273 CreateUserSettingsDirectory();
274 // Sets the current directory to the Setting dir
275 mCurrentDirectory = std2wx(GetUserSettingsDirectory());
277 // Window layout creation
278 wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
281 mSplitter1 = new wxSplitterWindow( this, -1);
283 // TreeCtrl on the left
288 //| wxTR_LINES_AT_ROOT
289 | wxTR_FULL_ROW_HIGHLIGHT
296 | wxTR_EDIT_LABELS //Use this style if you wish the user to be able to edit labels in the tree list control.
297 //wxTR_NO_BUTTONS For convenience to document that no buttons are to be drawn.
298 | wxTR_HAS_BUTTONS //Use this style to show + and - buttons to the left of parent items.
299 | wxTR_TWIST_BUTTONS //Use this style to show Mac-style twister buttons to the left of parent items. If both wxTR_HAS_BUTTONS and wxTR_TWIST_BUTTONS are given, twister buttons are generated.
300 //wxTR_NO_LINES Use this style to hide vertical level connectors.
301 | wxTR_FULL_ROW_HIGHLIGHT //Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree list control window. (This flag is ignored under Windows unless you specify wxTR_NO_LINES as well.)
302 | wxTR_LINES_AT_ROOT //Use this style to show lines between root nodes. Only applicable if wxTR_HIDE_ROOT is set and wxTR_NO_LINES is not set.
303 | wxTR_HIDE_ROOT //Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes.
304 // wxTR_ROW_LINES // Use this style to draw a contrasting border between displayed rows.
305 // wxTR_HAS_VARIABLE_ROW_HEIGHT// Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset.
306 // wxTR_SINGLE For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default.
307 | wxTR_MULTIPLE // Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected.
308 | wxTR_EXTENDED // Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases.)
309 //wxTR_DEFAULT_STYLE The set of flags that are closest to the defaults for the native control for a particular toolkit.
310 //| wxTR_VIRTUAL //The application provides items text on demand.
313 mTreeListCtrl = new wxTreeListCtrl(mSplitter1,
319 mTreeListCtrl->SetIndent(0);
320 mTreeListCtrl->SetLineSpacing(5);
325 wxPanel *rpanel = new wxPanel( mSplitter1, -1 );
327 wxBoxSizer *rsizer = new wxBoxSizer(wxHORIZONTAL);
328 // Right panel top/bottom split
329 mSplitter2 = new wxSplitterWindow( rpanel , -1);
332 mPanelImage = new wxPanel(mSplitter2,-1);
333 mPanelImage->SetBackgroundColour( wxColour(0,0,0) );
335 wxBoxSizer *isizer = new wxBoxSizer(wxHORIZONTAL );
336 mPanelImage->SetSizer( isizer );
338 // Fields view (bottom)
339 mFieldsView = new WxGimmickFieldsView(mSplitter2,-1,
343 mFieldsView->SetColors
344 ( GetSettings().Colour(DicomNode::Database),
345 GetSettings().BgColour(DicomNode::Database),
346 GetSettings().Colour(DicomNode::Patient),
347 GetSettings().BgColour(DicomNode::Patient),
348 GetSettings().Colour(DicomNode::Study),
349 GetSettings().BgColour(DicomNode::Study),
350 GetSettings().Colour(DicomNode::Series),
351 GetSettings().BgColour(DicomNode::Series),
352 GetSettings().Colour(DicomNode::Image),
353 GetSettings().BgColour(DicomNode::Image));
357 int wsize = size.GetWidth();
358 int hsize = size.GetHeight();
359 int previewhsize = 150;
360 int previewwsize = 400;
362 mSplitter2->SetMinimumPaneSize( previewhsize );
363 mSplitter2->SplitHorizontally( mPanelImage, mFieldsView,
364 hsize - previewhsize);
366 rsizer->Add( mSplitter2,1,wxGROW ,0);
368 rpanel->SetAutoLayout(true);
369 rpanel->SetSizer( rsizer );
373 mInteractor = new crea::creawxVTKRenderWindowInteractor(mPanelImage,-1);
374 mInteractor->UseCaptureMouseOn();
376 mViewer = vtkImageViewer2::New();
377 mViewer->SetupInteractor ( mInteractor );
378 mViewer->SetInput(mReader.GetImage(""));
380 isizer-> Add( mInteractor ,1,wxGROW ,0);
382 topsizer->Add( mSplitter1,1,wxGROW ,0);
385 mSplitter1->SetMinimumPaneSize( 200 );
386 mSplitter1->SplitVertically(mTreeListCtrl,
388 wsize - previewwsize );
391 // ProcessImageEvents();
392 SetSizer( topsizer );
395 mDatabaseListFile = GetUserSettingsDirectory();
396 mDatabaseListFile += "collections.txt";
401 ShowImage(mReader.GetImage(""));
405 //================================================================
409 #define VALID_FILE_SEPARATOR "\\"
410 #define INVALID_FILE_SEPARATOR "/"
412 #define INVALID_FILE_SEPARATOR "\\"
413 #define VALID_FILE_SEPARATOR "/"
416 //================================================================
417 const std::string& WxGimmick::GetUserSettingsDirectory()
419 if (mUserSettingsDirectory.size()==0)
421 #if defined(__GNUC__)
422 mUserSettingsDirectory = getenv("HOME");
423 #elif defined(_WIN32)
424 mUserSettingsDirectory = getenv("USERPROFILE");
426 mUserSettingsDirectory += "/.gimmick/";
427 boost::algorithm::replace_all( mUserSettingsDirectory,
428 INVALID_FILE_SEPARATOR ,
429 VALID_FILE_SEPARATOR);
431 return mUserSettingsDirectory;
433 //================================================================
435 //========================================================================
436 void WxGimmick::CreateUserSettingsDirectory()
438 if (! boost::filesystem::is_directory( GetUserSettingsDirectory() ) )
440 creaMessage("Gimmick!",1,"==> Directory '"<<GetUserSettingsDirectory()<<"' "
441 << "does not exist : creating it"<<std::endl);
443 if ( ! boost::filesystem::create_directory( GetUserSettingsDirectory() ) )
445 creaMessage("Gimmick!",1,"!! ERROR CREATING '"<<GetUserSettingsDirectory()<<"'");
449 //========================================================================
451 //================================================================
452 WxGimmick::~WxGimmick()
454 // std::cout << "WxGimmick::~WxGimmick()" <<std::endl;
455 if (mSaveConfigurationOnClose) SaveConfiguration();
458 // std::cout << "Reader stopped"<<std::endl;
460 DicomDatabaseListType::iterator i;
461 for (i =GetDicomDatabaseList().begin();
462 i!=GetDicomDatabaseList().end();
470 //================================================================
473 //================================================================
474 void WxGimmick::RebuildView()
478 mTreeListCtrl->DeleteRoot(); //DeleteAllItems();
479 // mTreeDefaultItemId = wxTreeItemId();
482 int nbattr = mSettings.GetMaxNumberOfColumns();
484 for (int j=0;j<nbattr; j++)
486 mTreeListCtrl->AddColumn (_T(""),
487 200, //DEFAULT_COL_WIDTH,
493 mTreeListCtrl->SetMainColumn (0);
494 mTreeListCtrl->SetColumnEditable (0, true);
496 mTreeRootId = mTreeListCtrl->AddRoot( _T(""),Icon_Root,Icon_Root);
498 // The collections columns legends
499 mCollectionsTitlesItemId =
500 CreateChildrenColumnsTitles(mTreeRootId,DicomNode::Database);
502 DicomDatabaseListType::iterator i;
503 for (i =GetDicomDatabaseList().begin();
504 i!=GetDicomDatabaseList().end();
507 UpdateDicomDatabaseView(*i);
510 mTreeListCtrl->Expand(mTreeRootId);
512 // mTreeListCtrl->ExpandAll(mTreeRootId);
513 // std::cout << "EO RebuildAll"<<std::endl;
515 //================================================================
519 //================================================================
520 void WxGimmick::UpdateDicomDatabaseView(DicomDatabase* db)
526 // Does the db exist ?
527 wxTreeItemIdValue cookie;
528 for (dbid = mTreeListCtrl->GetFirstChild(mTreeRootId,cookie);
530 dbid = mTreeListCtrl->GetNextChild(mTreeRootId,cookie))
532 data = (TreeItemData *)mTreeListCtrl->GetItemData(dbid);
533 if ((data->IsDatabase())&&(data->GetDicomNode()==db)) break;
536 // Not found : create
540 int iconid = Icon[DicomNode::Database];
543 // std::cout << " -> Creating item for '"<<db->GetLabel()<<"'"<<std::endl;
544 data = new TreeItemData(db);
545 dbid = mTreeListCtrl->AppendItem( mTreeRootId,
546 std2wx(db->GetLabel()),
550 data->SetItemId(dbid);
551 mTreeListCtrl->SetItemTextColour
552 (dbid,mSettings.Colour(DicomNode::Database));
553 mTreeListCtrl->SetItemBackgroundColour
554 (dbid,mSettings.BgColour(DicomNode::Database));
556 // The patients columns legends
557 CreateChildrenColumnsTitles(dbid,DicomNode::Patient);
560 // Increase UpdateTime to detect obsolete items after
562 data->UpdateTime()++;
564 DicomNode::ChildrenListType::iterator j;
565 for (j= db->GetChildrenList().begin();
566 j!=db->GetChildrenList().end();
569 UpdateDicomNodeView(*j,dbid);
572 DeleteObsoleteChildren(dbid);
574 mTreeListCtrl->EnsureVisible(dbid);
577 //================================================================
579 //================================================================
580 void WxGimmick::UpdateDicomNodeView(DicomNode* n,
581 const wxTreeItemId& parent)
585 // std::cout << "* UpdateDicomNodeView("<<n->GetLabel()<<")"<<std::endl;
587 wxTreeItemId newparent = parent;
590 if ((!mSettings.MergeStudySeries()) ||
591 (n->GetType() != DicomNode::Study))
593 // Does the item exist ?
594 wxTreeItemIdValue cookie;
595 for (newparent = mTreeListCtrl->GetFirstChild(parent,cookie);
597 newparent = mTreeListCtrl->GetNextChild(parent,cookie))
599 data = (TreeItemData *)mTreeListCtrl->GetItemData(newparent);
600 if (data->GetDicomNode() == n) break;
602 // Not found : create
603 if (!newparent.IsOk())
605 int image(Icon[n->GetType()]);
606 wxColour *colour(&mSettings.Colour(n->GetType()));
607 wxColour *bgcolour(&mSettings.BgColour(n->GetType()));
609 if (n->GetType()==DicomNode::Image)
611 // std::cout << "!!!Image"<<std::endl;
612 if (n->GetData<NodeData*>()!=0)
614 // std::cout << ">> n->GetData<NodeData*>()!=0" << std::endl;
615 if (n->GetData<NodeData*>()->IsLoaded())
617 colour = &mSettings.LoadedImageColour();
619 // std::cout << "<< n->GetData<NodeData*>()!=0" << std::endl;
623 data = new TreeItemData(n);
624 newparent = mTreeListCtrl->AppendItem(parent,
628 data->SetItemId(newparent);
629 mTreeListCtrl->SetItemTextColour(newparent,*colour);
630 mTreeListCtrl->SetItemBackgroundColour(newparent,*bgcolour);
632 UpdateColumns(newparent);
635 if (n->GetType()!=DicomNode::Image)
637 CreateChildrenColumnsTitles(newparent,n->GetType()+1);
643 UpdateColumns(newparent,true);
646 // synchonise update time with parent
647 TreeItemData * parent_data =
648 (TreeItemData *)mTreeListCtrl->GetItemData(parent);
649 data->UpdateTime() = parent_data->UpdateTime();
652 DicomNode::ChildrenListType::iterator i;
653 for (i=n->GetChildrenList().begin();
654 i!=n->GetChildrenList().end();
657 UpdateDicomNodeView(*i,newparent);
660 if (n->GetType() != DicomNode::Image)
661 DeleteObsoleteChildren(newparent);
664 //================================================================
666 //================================================================
667 void WxGimmick::UpdateColumns(wxTreeItemId& item,
671 (TreeItemData *)mTreeListCtrl->GetItemData(item);
672 DicomNode* node = data->GetDicomNode();
676 // Update only the first field (for #children update)
677 DicomNode* node2 = node;
678 // If Study and Series level are merged and node type is Series
679 // then have to get back to the Study level
680 if ((mSettings.MergeStudySeries())&&
681 (node->GetType() == DicomNode::Series))
682 node2 = node->GetParent();
685 lab += node2->GetFieldValueMap()
686 [ mSettings.GetColumnList(node2->GetType())[0].Key ];
688 if (node->GetType() != DicomNode::Image)
690 if (node->GetChildrenList().size()>0)
693 sprintf(sz," [%d]",node->GetNumberOfChildren());
697 mTreeListCtrl->SetItemText(item,std2wx(lab));
703 Settings::ColumnListType::iterator col;
704 // If Study and Series level are merged and node type is Series
705 // then have to fill the Study level cols first
706 if ((mSettings.MergeStudySeries())&&
707 (node->GetType() == DicomNode::Series))
709 DicomNode* node2 = node->GetParent();
710 for (col = mSettings.GetColumnList(node2->GetType()).begin();
711 col != mSettings.GetColumnList(node2->GetType()).end();
714 std::string s = node2->GetFieldValueMap()[col->Key];
719 sprintf(sz," [%d]",node->GetNumberOfChildren());
722 mTreeListCtrl->SetItemText (item, c, std2wx(s));
727 for (col = mSettings.GetColumnList(node->GetType()).begin();
728 col != mSettings.GetColumnList(node->GetType()).end();
731 std::string s = node->GetFieldValueMap()[col->Key];
732 if ((c==0)&&(node->GetType() != DicomNode::Image))
735 sprintf(sz," [%d]",node->GetNumberOfChildren());
738 mTreeListCtrl->SetItemText (item, c, std2wx(s));
744 //================================================================
746 //================================================================
747 wxTreeItemId WxGimmick::CreateChildrenColumnsTitles
751 // Creates the sub-level columns titles
753 = new TreeItemData(0);
754 wxTreeItemId id = mTreeListCtrl->AppendItem( item,
760 mTreeListCtrl->SetItemFont(id, *wxITALIC_FONT);
761 mTreeListCtrl->SetItemTextColour(id, mSettings.Colour(t));
762 mTreeListCtrl->SetItemBackgroundColour(id, mSettings.BgColour(t));
763 UpdateColumnsTitles(id,t);
766 //================================================================
768 //================================================================
769 void WxGimmick::UpdateColumnsTitles(wxTreeItemId& item,
772 // std::cout << "Update columns titles "<<t<<std::endl;
774 Settings::ColumnListType::iterator col;
775 for (col = mSettings.GetColumnList(t).begin();
776 col != mSettings.GetColumnList(t).end();
779 // std::cout << col->Name << std::endl;
780 mTreeListCtrl->SetItemText (item, c, std2wx(col->Name));
784 //================================================================
787 //================================================================
788 void WxGimmick::DeleteObsoleteChildren(wxTreeItemId& id)
791 TreeItemData * parent_data =
792 (TreeItemData *)mTreeListCtrl->GetItemData(id);
795 wxTreeItemIdValue cookie;
796 std::vector<wxTreeItemId> children;
797 for (child = mTreeListCtrl->GetFirstChild(id,cookie);
799 child = mTreeListCtrl->GetNextChild(id,cookie))
801 children.push_back(child);
803 std::vector<wxTreeItemId>::iterator i;
804 for (i=children.begin();i!=children.end();++i)
807 (TreeItemData *)mTreeListCtrl->GetItemData(*i);
809 ((data->GetDicomNode()>0) &&
810 ((data->UpdateTime() != parent_data->UpdateTime()))) ||
811 ((data->IsDicomNode()) &&
812 (data->GetDicomNode()==0))
815 // std::cout << "DOBSC="<<mTreeListCtrl->GetItemText(*i)<<std::endl;
816 mTreeListCtrl->Delete(*i);
820 //================================================================
822 //================================================================
823 void WxGimmick::OpenOrNewDatabase(bool open)
827 long style = wxFD_SAVE | wxFD_OVERWRITE_PROMPT;
828 if (open) style = wxOPEN | wxFILE_MUST_EXIST;
829 std::string wc("*.");
830 wc += GetDatabaseExtension();
832 // TO DO : Handler give their wildcards
833 wxFileDialog* FD = new wxFileDialog( 0,
841 if (FD->ShowModal()!=wxID_OK) return;
843 std::string filename = wx2std (FD->GetPath());
844 mCurrentDirectory = FD->GetDirectory();
848 boost::filesystem::path filepath(filename);
849 boost::filesystem::change_extension(filepath,GetDatabaseExtension());
850 if ( boost::filesystem::exists(filepath) )
852 boost::filesystem::remove(filepath);
854 LG : works on Linux but not Windows :
855 if ( ! boost::filesystem::remove(filepath) )
857 wxMessageBox(_T("Could not overwrite ")
858 +std2wx(filepath.string()),
869 DicomDatabase* db = new DicomDatabase(filename);
876 wxMessageBox(_T("An error occured while opening ")
886 wxGetTextFromUser(_T("Enter collection name"),_T("New collection"),
888 db->SetName(wx2std(collname));
893 wxMessageBox(_T("An error occured while creating ")
901 GetDicomDatabaseList().push_back(db);
902 UpdateDicomDatabaseView(db);
905 //================================================================
908 //================================================================
909 void WxGimmick::LoadConfiguration()
912 // std::cout << "WxGimmick : Reading config"<<std::endl;
914 // std::cout << "==> Loading collections from '"<<mDatabaseListFile
918 s.open(mDatabaseListFile.c_str());
925 if (str.size()==0) continue;
927 std::vector<std::string> tokens;
928 boost::split( tokens, str, boost::is_any_of("\t") );
930 DicomDatabase* db = new DicomDatabase(tokens[0]);
932 // std::cout << " -> Loading collection '"<<tokens[0]<<"'"<<std::endl;
934 if (tokens.size()==2)
936 db->SetName(tokens[1]);
941 GetDicomDatabaseList().push_back(db);
942 db->DBLoadChildren(db,DicomNode::Patient);
943 if (mSettings.HasActiveComparator(DicomNode::Patient))
946 ( mSettings.GetActiveComparator(DicomNode::Patient) );
951 // std::cout << " ... ERROR !"<<std::endl;
959 std::cout << "ERROR opening "<<mDatabaseListFile<<std::endl;
963 mTreeListCtrl->SetBackgroundColour(mSettings.BgColour(DicomNode::Database));
964 if (GetDicomDatabaseList().begin() !=
965 GetDicomDatabaseList().end() )
967 mFieldsView->UpdateFields(*GetDicomDatabaseList().begin());
973 //================================================================
975 //================================================================
976 void WxGimmick::SaveConfiguration()
979 creaMessage("Gimmick!",1,"Gimmick! : Saving configuration..."<<std::endl);
981 creaMessage("Gimmick!",1,"Gimmick! : ==> Saving collections in '"
982 <<mDatabaseListFile<<"'"<<std::endl);
985 s.open(mDatabaseListFile.c_str());
988 creaError("Gimmick! : error opening '"<<mDatabaseListFile<<"'");
991 DicomDatabaseListType::iterator i;
992 for (i =GetDicomDatabaseList().begin();
993 i!=GetDicomDatabaseList().end();
996 s << (*i)->GetFileName() << "\t";
997 s << (*i)->GetName() << std::endl;
1003 //================================================================
1006 //================================================================
1007 void WxGimmick::OnClose(wxCloseEvent& event)
1009 if (mSaveConfigurationOnClose) SaveConfiguration();
1011 //================================================================
1013 //================================================================
1014 void WxGimmick::OnItemActivated(wxTreeEvent& event)
1020 // std::cout << "OnItemActivated" <<std::endl;
1021 wxTreeItemId itemId = event.GetItem();
1022 if (mTreeListCtrl->IsExpanded(itemId))
1024 mTreeListCtrl->Collapse(itemId);
1028 mTreeListCtrl->Expand(itemId);
1031 //================================================================
1033 //================================================================
1034 void WxGimmick::LoadChildren(wxTreeItemId& id)
1036 TreeItemData *item = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1039 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1040 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1043 // If children not already loaded : do it
1045 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1046 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1049 // Some new children loaded
1051 if (mSettings.HasActiveComparator
1052 (item->GetDicomNode()->GetType()+1))
1054 /* std::cout << "Sorting using '"
1055 << mSettings.GetActiveComparator
1056 (item->GetDicomNode()->GetType()+1).GetName()
1059 item->GetDicomNode()->SortChildren
1060 ( mSettings.GetActiveComparator
1061 (item->GetDicomNode()->GetType()+1)
1063 // std::cout << "ok"<<std::endl;
1066 DicomNode::ChildrenListType::iterator i;
1067 for (i=item->GetDicomNode()->GetChildrenList().begin();
1068 i!=item->GetDicomNode()->GetChildrenList().end();
1071 UpdateDicomNodeView(*i,id);
1074 // EO If children not already loaded
1078 //================================================================
1081 //================================================================
1082 void WxGimmick::OnItemExpanded(wxTreeEvent& event)
1085 // std::cout << "* Expanded *"<<std::endl;
1090 wxTreeItemId itemId = event.GetItem();
1091 LoadChildren(itemId);
1095 // expand if collapsed and collapse if expanded ...
1096 TreeItemData *item =
1097 (TreeItemData *)mTreeListCtrl->GetItemData(itemId);
1100 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1101 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1104 // If children not already loaded : do it
1106 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1107 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1111 // Some new children loaded
1113 if (mSettings.HasActiveComparator
1114 (item->GetDicomNode()->GetType()+1))
1116 /* std::cout << "Sorting using '"
1117 << mSettings.GetActiveComparator
1118 (item->GetDicomNode()->GetType()+1).GetName()
1121 item->GetDicomNode()->SortChildren
1122 ( mSettings.GetActiveComparator
1123 (item->GetDicomNode()->GetType()+1)
1125 // std::cout << "ok"<<std::endl;
1128 // If images : sort them
1129 if (item->IsDicomNode())
1131 if (item->GetDicomNode()->GetType()==DicomNode::Series)
1135 LexicographicalDicomNodeComparator compare;
1136 // DicomNodeImageImageNumberComparator c1;
1138 DicomNodeImageSliceLocationComparator c1;
1139 DicomNodeImageImageNumberComparator c2;
1140 DicomNodeImageFileNameComparator cn;
1144 // std::cout << "SORT"<<std::endl;
1145 item->GetDicomNode()->SortChildren(compare);
1146 // std::cout << "EO SORT"<<std::endl;
1154 DicomNode::ChildrenListType::iterator i;
1155 for (i=item->GetDicomNode()->GetChildrenList().begin();
1156 i!=item->GetDicomNode()->GetChildrenList().end();
1159 UpdateDicomNodeView(*i,itemId);
1162 // EO If children not already loaded
1165 // mTreeListCtrl->Expand(itemId);
1168 //================================================================
1172 //=====================================================================
1173 void WxGimmick::InsertRoot(wxTreeItemId& id, Root* r)
1176 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1181 data->GetDicomNode()->GetDicomDatabase()->LoadAll();
1182 printf(">>>>>> Time to load all = %ldms \n",sw.Time());
1184 UpdateRootView(data->GetDicomNode()->GetDicomDatabase());
1187 if (data->IsDicomNode())
1190 r->Insert(data->GetDicomNode());
1191 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1194 else if (data->IsDatabase())
1197 DicomNode::ChildrenListType::iterator j;
1198 for (j= data->GetDicomNode()->GetChildrenList().begin();
1199 j!=data->GetDicomNode()->GetChildrenList().end();
1204 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1210 //=====================================================================
1214 //=================================================
1215 void WxGimmick::DeleteDicomDatabase(wxTreeItemId& id,
1219 DicomDatabaseListType::iterator i = find(GetDicomDatabaseList().begin(),
1220 GetDicomDatabaseList().end(),
1223 GetDicomDatabaseList().erase(i);
1224 mTreeListCtrl->Delete(id);
1226 //=================================================
1230 //=====================================================================
1232 void WxGimmick::OnItemRightClick(wxTreeEvent& event)
1235 wxTreeItemId itemId = event.GetItem();
1238 wxPoint clientpt = event.GetPoint();
1239 wxPoint screenpt = ClientToScreen(clientpt);
1240 ShowMenu(itemId, clientpt);
1244 //=====================================================================
1248 //=====================================================================
1249 void WxGimmick::ShowMenu(wxTreeItemId id, const wxPoint& pt)
1252 // std::cout << "ShowMenu" <<std::endl;
1254 TreeItemData *data =
1255 (TreeItemData *)mTreeListCtrl->GetItemData(id);
1261 title << wxT("Menu for ") << mTreeListCtrl->GetItemText(id);
1265 title = wxT("Menu for no particular item");
1272 if (id==mCollectionsTitlesItemId)
1274 menu.Append(PopUp_NewCollection, _T("&New collection"));
1275 menu.Append(PopUp_OpenCollection, _T("&Open collection"));
1279 if (data->IsDatabase())
1281 wxMenu* addmenu = new wxMenu;
1282 addmenu->Append(PopUp_AddDirectory, _T("Scan &Directory"));
1283 addmenu->Append(PopUp_AddFile, _T("Select &File(s)"));
1284 // addmenu->Append(PopUp_AddRawFile, _T("Add &Raw image"));
1285 menu.AppendSubMenu(addmenu, _T("&Add image(s) to collection..."));
1286 menu.Append(PopUp_CloseCollection, _T("&Close collection"));
1287 menu.Append(PopUp_DeleteCollection, _T("&Delete collection"));
1289 if (data->IsDicomNode())
1294 std::string str("&Remove ");
1295 str += data->GetDicomNode()->GetTypeName();
1296 menu.Append(PopUp_Remove, std2wx(str));
1300 if ((data->GetDicomNode()>0)&&
1301 ( data->GetDicomNode()->GetType()<DicomNode::Image))
1303 int ctype = data->GetDicomNode()->GetType()+1;
1304 if (mSettings.HasActiveComparator(ctype))
1306 wxMenu* sortmenu = new wxMenu;
1308 Settings::ComparatorsList::iterator i;
1309 for (i =mSettings.GetComparatorsList(ctype).begin();
1310 i !=mSettings.GetComparatorsList(ctype).end();
1313 sortmenu->AppendRadioItem(PopUp_Sort+n, std2wx(i->GetName()));
1317 sortmenu->Check(PopUp_Sort+
1318 mSettings.GetActiveComparatorIndex(ctype)
1321 std::string sortmenustr("&Sort ");
1322 sortmenustr += DicomNode::GetPluralTypeName(ctype);
1323 sortmenustr += " by...";
1324 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1325 menu.AppendSubMenu(sortmenu,std2wx(sortmenustr));
1328 item->GetDicomNode()->SortChildren
1329 ( mSettings.GetActiveComparator
1330 (item->GetDicomNode()->GetType()+1)
1332 std::cout << "ok"<<std::endl;
1337 // Event : user can customize the menu
1339 ev(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU,this,id);
1343 ev.SetDicomNode(data->GetDicomNode());
1345 GetEventHandler()->ProcessEvent(ev);
1348 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1349 menu.Append(PopUp_Settings, wxT("&Settings..."));
1350 menu.Append(PopUp_About, wxT("&About..."));
1355 wxMenu* newmenu = new wxMenu;
1356 wxMenu* openmenu = new wxMenu;
1357 Tree::RootHandlerListType::iterator h;
1359 for (h= Tree::GetRootHandlerList().begin();
1360 h!=Tree::GetRootHandlerList().end();
1363 if ((*h)->SupportsNew())
1365 newmenu->Append(PopUp_New+i, std2wx((*h)->GetName()));
1367 if ((*h)->SupportsOpen())
1368 openmenu->Append(PopUp_Open+i, std2wx((*h)->GetName()));
1372 menu.AppendSubMenu(openmenu, _T("&Open"));
1373 menu.AppendSubMenu(newmenu, _T("&New"));
1377 if ((data->IsDatabase())||(data->IsDicomNode()))
1379 Root* itroot = data->GetDicomNode()->GetDicomDatabase();
1380 // if (!itroot) itroot = data->GetDicomNode()->GetRoot();
1381 wxMenu* insertmenu = new wxMenu;
1382 bool hasone = false;
1384 Tree::RootListType::iterator j;
1385 for (j = mTree->GetDatabaseList().begin();
1386 j != mTree->GetDatabaseList().end();
1389 // std::cout << (*j)->GetName() << " "
1390 // << (*j)->GetTypeName()
1391 // << " i="<<(*j)->SupportsInsert()<<std::endl;
1392 if ( ((*j)!=itroot) && ((*j)->SupportsInsert()) )
1394 insertmenu->Append(PopUp_Insert+i,
1395 std2wx((*j)->GetName()));
1401 if (hasone) menu.AppendSubMenu(insertmenu, _T("&Insert into"));
1403 if (data->IsDatabase())
1405 menu.Append(PopUp_Close, wxT("&Close"));
1407 if (data->IsDicomNode() && data->GetDicomNode()->GetDicomDatabase()->SupportsRemove())
1409 menu.Append(PopUp_Remove, wxT("&Remove"));
1417 PopupMenu(&menu, pt);
1418 #endif // wxUSE_MENUS
1420 // std::cout << "EO ShowMenu" <<std::endl;
1422 //=====================================================================
1424 //=====================================================================
1425 // Pop up menu callbacks
1426 void WxGimmick::OnPopUpAbout(wxCommandEvent& event)
1428 wxMessageBox( _T("Give me my medical images quick ! \n\n (c) CREATIS-LRMN 2008\n laurent.guigues@creatis.insa-lyon.fr"),
1430 wxOK | wxICON_INFORMATION, this);
1432 //=====================================================================
1434 //=====================================================================
1435 void WxGimmick::OnPopUpSettings(wxCommandEvent& event)
1437 WxGimmickSettingsDialog* s =
1438 new WxGimmickSettingsDialog(this);
1442 //=====================================================================
1444 //=====================================================================
1445 void WxGimmick::OnPopUpNewCollection(wxCommandEvent& event)
1448 OpenOrNewDatabase(false);
1450 //=====================================================================
1454 //=====================================================================
1455 void WxGimmick::OnPopUpOpenCollection(wxCommandEvent& event)
1458 OpenOrNewDatabase(true);
1460 //=====================================================================
1463 //=====================================================================
1464 void WxGimmick::OnPopUpCloseCollection(wxCommandEvent& event)
1466 if (wxMessageBox(_T("This will remove this collection from your list of collections but will not delete the collection's file on disk. Proceed ?"),_T("Confirm"),wxYES_NO,this)==wxNO) return;
1469 // std::cout << "OnPopUpClose"<<std::endl;
1470 // wxTreeItemId id = event.GetId();
1471 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1472 DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
1473 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1474 DeleteDicomDatabase(mItemOfMenu,r);
1476 //=====================================================================
1478 //=====================================================================
1479 void WxGimmick::OnPopUpDeleteCollection(wxCommandEvent& event)
1481 if (wxMessageBox(_T("This will physically delete the collection's file on disk and cannot be reverted. Proceed ?"),_T("Confirm"),wxYES_NO,this)==wxNO) return;
1486 // std::cout << "OnPopUpClose"<<std::endl;
1487 // wxTreeItemId id = event.GetId();
1488 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1489 DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
1491 wxRemoveFile(std2wx(r->GetFileName()));
1492 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1493 DeleteDicomDatabase(mItemOfMenu,r);
1496 //=====================================================================
1498 void DisplayUpdateSummary( DicomDatabase::UpdateSummary& summary,
1501 std::stringstream mess;
1502 mess << "Dirs\tscanned\t\t\t: " << summary.scanned_dirs << "\n";
1503 mess << "Files\tscanned\t\t\t: " << summary.scanned_files << "\n";
1504 mess << "Files\thandled\t\t\t: " << summary.handled_images << "\n\n";
1505 mess << "Patients\tadded\t\t: " << summary.added_patients<< "\n";
1506 mess << "Studies\tadded\t\t: " << summary.added_studies<< "\n";
1507 mess << "Series\tadded\t\t: " << summary.added_series<< "\n";
1508 mess << "Images\tadded\t\t: " << summary.added_images<< "\n\n";
1510 sprintf(times,"Time to parse dir \t\t: %ld ms \t%d°/o\nTime to read files info \t: %ld ms \t%d°/o\nTime to update structs \t: %ld ms \t%d°/o\nTime to update database \t: %ld ms \t%d°/o\nTotal time \t\t\t: %ld ms",
1512 (int)( summary.parse_time*100./summary.total_time),
1513 summary.file_scan_time,
1514 (int)(summary.file_scan_time*100./summary.total_time),
1515 summary.update_structs_time,
1516 (int)(summary.update_structs_time*100./summary.total_time),
1517 summary.update_database_time,
1518 (int)(summary.update_database_time*100./summary.total_time),
1519 summary.total_time );
1523 wxMessageBox(std2wx(mess.str()),_T("Update summary"),wxOK,parent);
1527 //=====================================================================
1528 void WxGimmick::OnPopUpAddFile(wxCommandEvent& event)
1530 long style = wxOPEN | wxFILE_MUST_EXIST | wxFD_MULTIPLE;
1531 std::string wc("*.*");
1532 wxFileDialog* FD = new wxFileDialog( 0,
1540 if (FD->ShowModal()==wxID_OK)
1544 mCurrentDirectory = FD->GetDirectory();
1545 wxArrayString files;
1546 FD->GetPaths(files);
1548 std::vector<std::string> filenames;
1549 for (i=0;i<files.GetCount();++i)
1550 filenames.push_back(wx2std(files[i]));
1553 TreeItemData *data =
1555 mTreeListCtrl->GetItemData(mItemOfMenu);
1556 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1557 DicomDatabase::UpdateSummary summary;
1558 wxProgressDialog* progress =
1559 new wxProgressDialog(_T("Adding file(s)"),
1564 wxPD_ESTIMATED_TIME |
1565 wxPD_REMAINING_TIME |
1568 db->AddFiles(filenames,progress,summary);
1570 progress->Pulse(_T("Updating view..."));
1571 UpdateDicomDatabaseView(db);
1573 DisplayUpdateSummary(summary,this);
1577 //=====================================================================
1579 //=====================================================================
1580 void WxGimmick::OnPopUpAddRawFile(wxCommandEvent& event)
1582 wxMessageBox(_T("Not yet implemented !"),_T("Sorry"),wxOK,this);
1584 //=====================================================================
1586 //=====================================================================
1587 void WxGimmick::OnPopUpAddDirectory(wxCommandEvent& event)
1589 long style = wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST;
1592 _T("Select directory"),
1596 if (FD->ShowModal()==wxID_OK)
1599 bool recurse = false;
1600 if (wxMessageBox(_T("Recurse into sub-directories ?"),
1601 _T("Scan directory"),
1602 wxYES_NO,this ) == wxYES)
1608 wxProgressDialog* progress =
1609 new wxProgressDialog(_T("Scanning directory"),
1610 _T("Parsing directory"),
1614 wxPD_ESTIMATED_TIME |
1615 wxPD_REMAINING_TIME |
1617 DicomDatabase::UpdateSummary summary;
1619 std::string dirname = wx2std (FD->GetPath()) ;
1620 mCurrentDirectory = FD->GetPath();
1621 TreeItemData *data =
1623 mTreeListCtrl->GetItemData(mItemOfMenu);
1624 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1625 db->AddDirectory(dirname,recurse,progress,summary);
1627 progress->Pulse(_T("Updating view..."));
1628 UpdateDicomDatabaseView(db);
1631 DisplayUpdateSummary(summary,this);
1633 if (summary.cancelled_by_user)
1635 std::cout << "!! Cancelled by user !!"<<std::endl;
1641 //=====================================================================
1643 //=====================================================================
1644 void WxGimmick::OnPopUpRemove(wxCommandEvent& event)
1648 wxMessageBox(_T("Not yet implemented"),_T("Sorry !"),wxOK);
1652 // wxTreeItemId id = event.GetId();
1653 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1655 std::string mess("Remove ");
1656 mess += data->GetDicomNode()->GetTypeName();
1657 mess += " from collection ?";
1658 int answer = wxMessageBox(std2wx(mess), _T("Confirm"), wxYES_NO);
1659 if (answer == wxNO) return;
1661 if ( mTreeListCtrl->IsSelected(mItemOfMenu) )
1663 wxTreeItemId next = mTreeListCtrl->GetNextSibling(mItemOfMenu);
1666 mTreeListCtrl->SelectItem(next);
1674 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1675 db->Remove(data->GetDicomNode());
1676 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1677 // TODO : Optimize update only parent's branch
1678 UpdateDicomDatabaseView(db);
1679 // DeleteDicomDatabase(mItemOfMenu,r);
1681 //=====================================================================
1683 //=====================================================================
1684 void WxGimmick::OnPopUpSort(wxCommandEvent& event)
1687 // std::cout << "OnPopUpSort"<<std::endl;
1688 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1689 int index = event.GetId() - PopUp_Sort;
1690 DicomNode* node = data->GetDicomNode();
1691 DicomNode::Type ctype = node->GetType()+1;
1692 mSettings.SetActiveComparatorIndex(ctype,index);
1694 if (node->ChildrenLoaded())
1697 mTreeListCtrl->DeleteChildren(mItemOfMenu);
1699 /* std::cout << "Sorting using '"
1700 << mSettings.GetActiveComparator(ctype).GetName()
1703 node->SortChildren ( mSettings.GetActiveComparator(ctype) );
1704 // std::cout << "ok"<<std::endl;
1708 CreateChildrenColumnsTitles(mItemOfMenu,ctype);
1709 DicomNode::ChildrenListType::iterator i;
1710 for (i=node->GetChildrenList().begin();
1711 i!=node->GetChildrenList().end();
1714 UpdateDicomNodeView(*i,mItemOfMenu);
1718 //=====================================================================
1721 //=====================================================================
1722 void WxGimmick::OnPopUpUser(wxCommandEvent& event)
1724 // std::cout << "OnPopUpUser"<<std::endl;
1727 //=====================================================================
1729 //=================================================
1730 void WxGimmick::CreateImageList(int size)
1734 mTreeListCtrl->SetImageList(NULL);
1743 // should correspond to Icon_xxx enum
1744 icons[Icon_Patient] = wxIcon(patient_xpm);
1745 icons[Icon_Study] = wxIcon(study_xpm);
1746 icons[Icon_Series] = wxIcon(series_xpm);
1747 icons[Icon_Image] = wxIcon(image_xpm);
1748 icons[Icon_Database] = wxIcon(database_xpm);
1749 icons[Icon_Folder] = wxIcon(folder_xpm);
1750 icons[Icon_DicomDir] = wxIcon(dicomdir_xpm);
1751 icons[Icon_Root] = wxIcon(root_xpm);
1754 // mFirstRootIconIndex = 8;
1757 Tree::RootHandlerListType::iterator h;
1759 for (h= Tree::GetDatabaseHandlerList().begin();
1760 h!=Tree::GetDatabaseHandlerList().end();
1763 icons[mFirstRootIconIndex+i] = (*h)->GetIcon();
1767 unsigned int NbIcons = 8;//mFirstRootIconIndex + i;
1768 // Make an image list containing small icons
1769 wxImageList *images = new wxImageList(size, size, true);
1771 int sizeOrig = icons[0].GetWidth();
1772 for ( size_t i = 0; i < NbIcons; i++ )
1774 if ( size == sizeOrig )
1776 images->Add(icons[i]);
1780 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
1783 mTreeListCtrl->AssignImageList(images);
1785 //=================================================
1794 //================================================================
1795 bool WxGimmick::IsImageSelectable(DicomNode* node)
1797 int rows = node->ImageGetRows();
1798 int cols = node->ImageGetColumns();
1799 int frms = node->ImageGetFrames();
1801 // std::cout << "R/C/F = " << rows << "/"<< cols <<"/"<<frms<<std::endl;
1805 else if (cols>0) dim=2;
1806 else if (rows>0) dim=1;
1810 std::cout << "Unknown image dimension : cannot select !"
1814 else if (dim>mSelectionMaxImageDimension)
1816 std::cout << "Selecting "<<dim<<"D images is not allowed !"
1821 if ( mTreeListCtrl->GetSelectionSize() == 0 )
1823 mCurrentSelectionImageSize[0] = cols;
1824 mCurrentSelectionImageSize[1] = rows;
1825 mCurrentSelectionImageSize[2] = frms;
1830 if ( dim == mSelectionMaxImageDimension )
1832 std::cout << "Cannot add this image to selection : would result in a "<<dim+1<<"D image !" << std::endl;
1835 if ( ( cols != mCurrentSelectionImageSize[0] ) ||
1836 ( rows != mCurrentSelectionImageSize[1] ) ||
1837 ( frms != mCurrentSelectionImageSize[2] ) )
1839 std::cout << "Cannot add this image to selection : image size is incomptatible with currently selected images" << std::endl;
1843 // std::cout << "Selecting : "<<node->ImageGetFullFileName() << std::endl;
1846 //================================================================
1848 //================================================================
1849 void WxGimmick::OnSelChanging(wxTreeEvent& event)
1852 wxTreeItemId id = event.GetItem();
1855 std::cout << "INTERNAL ERROR : ID NOT OK"<<std::endl;
1860 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1861 if (data->IsDicomNode())
1863 if (data->GetDicomNode()>0)
1865 // An image was selected
1866 if (data->GetDicomNode()->GetType()==DicomNode::Image)
1868 if (IsImageSelectable(data->GetDicomNode())) event.Allow();
1870 // A series was selected
1871 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
1873 // If images not loaded do it
1875 // can be selected if all its images can
1877 wxTreeItemIdValue cookie;
1878 for (child = mTreeListCtrl->GetFirstChild(id,cookie);
1880 child = mTreeListCtrl->GetNextChild(id,cookie))
1882 TreeItemData *cdata =
1883 (TreeItemData *)mTreeListCtrl->GetItemData(child);
1884 if ((cdata->IsDicomNode())&&
1885 (cdata->GetDicomNode()>0)&&
1886 (cdata->GetDicomNode()->GetType()==DicomNode::Image)&&
1887 (!IsImageSelectable(cdata->GetDicomNode())))
1895 //================================================================
1897 //================================================================
1898 void WxGimmick::OnSelChanged(wxTreeEvent& event)
1900 // wxBusyCursor busy;
1901 // std::vector<wxTreeItemId> items;
1902 // GetSelectedItems(items);
1904 std::vector<DicomNode*>::iterator i;
1905 for (i=nodes.begin();i!=nodes.end();++i)
1907 std::cout << "'" << (*i)->GetFieldValue("FullFileName")
1908 << "'" << std::endl;
1910 std::cout << "++++++++++++++++++++" << std::endl;
1912 // ShowImage(mReader.GetImage(""));
1914 bool no_image = true;
1916 static int max = 1000;
1919 // if (items.size()>0)
1922 // Update image preview : send requests to the MTImageReader
1923 // bool first = true;
1924 // std::vector<wxTreeItemId>::iterator i;
1925 // for (i=items.begin();i!=items.end();++i)
1931 DicomNode* node = GetDicomNodeOfItem(items[0]);
1933 // Update dicom fields panel
1934 mFieldsView->UpdateValues(node);
1938 wxTreeItemId item = mTreeListCtrl->GetCurrent();
1940 DicomNode* n = GetDicomNodeOfItem(item);
1942 if (n) mFieldsView->UpdateValues(n);
1945 (n->GetType()==DicomNode::Image) )
1950 //if (i==items.begin())
1951 mCurImageItemToShow = item;
1953 int maxprio = mReader.GetMaximalPriority();
1954 int prio = maxprio + 1000;
1955 wxTreeItemId sib = item; //GetTreeListCtrl()->GetNextSibling(*i);
1958 DicomNode* nsib = GetDicomNodeOfItem(sib);
1961 // std::cout << "-- Request '"
1962 // << nsib->GetFieldValue("FullFileName")
1963 // << "' prio="<<prio<<std::endl;
1964 mReader.Request(this,
1965 nsib->ImageGetFullFileName(),
1967 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
1971 sib = GetTreeListCtrl()->GetNextSibling(sib);
1973 prio = maxprio + 1000;
1974 sib = GetTreeListCtrl()->GetPrevSibling(item);
1977 DicomNode* nsib = GetDicomNodeOfItem(sib);
1980 // std::cout << "-- Request '"
1981 // << nsib->GetFieldValue("FullFileName")
1982 // << "' prio="<<prio<<std::endl;
1983 mReader.Request(this,
1984 nsib->ImageGetFullFileName(),
1986 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
1990 sib = GetTreeListCtrl()->GetPrevSibling(sib);
1992 // mImageFileNameToNode[n->GetFieldValue("FullFileName")] = n;
1995 ProcessImageEvents();
1997 // std::cout << "* Selection changed * (im)"<<std::endl;
1999 //---------------------------------------------------------------------
2001 WxGimmickEvent ev(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED,
2005 GetEventHandler()->ProcessEvent(ev);
2007 if (no_image) ShowImage(mReader.GetImage(""));
2010 //================================================================
2012 //================================================================
2013 void WxGimmick::ShowImage(vtkImageData* im)
2015 // wxBusyCursor busy;
2017 int x1,x2,y1,y2,z1,z2;
2019 im->GetSpacing(spx,spy,spz);
2020 im->GetExtent (x1,x2,y1,y2,z1,z2);
2023 std::cout << x1 << "-"<<x2<<std::endl;
2024 std::cout << y1 << "-"<<y2<<std::endl;
2025 std::cout << z1 << "-"<<z2<<std::endl;
2026 std::cout << spx << "-"<<spy<<"-"<<spz<<std::endl;
2050 vtkCamera *camera = mViewer->GetRenderer()->GetActiveCamera();
2052 camera->SetViewUp ( spx*0, -spy*1, spz*0);
2053 camera->SetPosition( spx*(x1+x2)/2, spy*(y1+y2)/2, -spz*10000000);
2054 camera->SetFocalPoint ( spx*(x1+x2)/2 , spy*(y1+y2)/2 , spz*0);
2056 camera->ComputeViewPlaneNormal();
2057 camera->SetParallelScale( spx*(x2-x1)/2.0 );
2061 mViewer->SetInput( im );
2062 mViewer->SetSlice( 0 );
2063 mInteractor->Render();
2065 //================================================================
2072 //================================================================
2074 OnMultiThreadImageReaderEvent(const std::string& filename,
2075 MultiThreadImageReaderUser::EventType e,
2076 vtkImageData* image)
2078 if (filename.size()==0)
2080 mImageEventQueue.push_back(ImageEventType(image));
2083 std::map<std::string,DicomNode*>::iterator i;
2084 i = mImageFileNameToNode.find(filename);
2085 if (i!=mImageFileNameToNode.end())
2087 wxTreeItemId id = i->second->GetData<NodeData*>()->GetTreeItemData()->GetItemId();
2088 mImageEventQueue.push_back(ImageEventType(id,image));
2091 //================================================================
2093 //================================================================
2094 // Processes the queue of image events
2095 void WxGimmick::ProcessImageEvents()
2097 // std::cout << "++++++++++ ProcessImageEvents " << std::endl;
2098 MultiThreadImageReaderEventLock();
2101 while (!mImageEventQueue.empty())
2103 ImageEventType e = mImageEventQueue.front();
2104 mImageEventQueue.pop_front();
2109 mTreeListCtrl->SetItemTextColour(e.item,
2110 mSettings.LoadedImageColour());//wxImageLoadedColour);
2111 TreeItemData *data =
2112 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2113 data->SetLoaded(true);
2115 if (mCurImageItemToShow == e.item)
2120 else if (!mCurImageItemToShow.IsOk())
2125 else if (e.item.IsOk())
2127 mTreeListCtrl->SetItemTextColour(e.item,mSettings.Colour(DicomNode::Image)); //.wxImageUnloadedColour);
2128 TreeItemData *data =
2129 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2130 data->SetLoaded(false);
2133 mImageEventQueue.clear();
2134 MultiThreadImageReaderEventUnlock();
2135 // std::cout << "++++++++++ END ProcessImageEvents " << std::endl;
2137 //================================================================
2139 //================================================================
2140 void WxGimmick::OnInternalIdle()
2142 ProcessImageEvents();
2145 // Show tip if no collection
2146 if (GetDicomDatabaseList().size()==0)
2150 mJustStarted = false;
2154 //================================================================
2157 //================================================================
2158 // LG : For the moment any selection is valid but in the future
2159 // incomplete selections can be invalid...
2160 bool WxGimmick::IsSelectionValid()
2162 return (mTreeListCtrl->GetSelectionSize()>0);
2164 //================================================================
2166 //================================================================
2167 void WxGimmick::GetSelectedFiles(std::vector<std::string>& f)
2169 wxArrayTreeItemIds id;
2170 // TO DO : TEST THAT STYLE IS MULTIPLE
2171 unsigned int nb = mTreeListCtrl->GetSelections(id);
2173 for (unsigned int i=0; i<nb; ++i)
2175 TreeItemData *data =
2176 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2177 if ((data) && (data->IsDicomNode()))
2179 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2181 f.push_back ( data->GetDicomNode()->ImageGetFullFileName() );
2183 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2185 DicomNode::ChildrenListType::iterator j;
2186 for (j =data->GetDicomNode()->GetChildrenList().begin();
2187 j!=data->GetDicomNode()->GetChildrenList().end();
2190 f.push_back((*j)->ImageGetFullFileName());
2196 //================================================================
2198 //================================================================
2199 void WxGimmick::GetSelectedImages(std::vector<vtkImageData*>& f)
2201 wxArrayTreeItemIds id;
2202 // TO DO : TEST THAT STYLE IS MULTIPLE
2203 unsigned int nb = mTreeListCtrl->GetSelections(id);
2206 // Collect the brute vector of Image nodes
2207 std::vector<DicomNode*> im;
2208 for (unsigned int i=0; i<nb; ++i)
2210 TreeItemData *data =
2211 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2212 if ((data) && (data->IsDicomNode()))
2214 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2216 im.push_back ( data->GetDicomNode() );
2219 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2221 DicomNode::ChildrenListType::iterator j;
2222 for (j =data->GetDicomNode()->GetChildrenList().begin();
2223 j!=data->GetDicomNode()->GetChildrenList().end();
2226 im.push_back ( *j );
2231 // Create the output data
2234 // Only one image : give it
2235 vtkImageData* out = vtkImageData::New();
2236 out->ShallowCopy(mReader.GetImage(im.front()->ImageGetFullFileName()));
2239 else if (im.size()>1)
2241 vtkImageData* first = mReader.GetImage( im.front()->ImageGetFullFileName() );
2242 if (first->GetDataDimension()==2)
2245 vtkImageData* out = vtkImageData::New();
2246 out->CopyStructure(first);
2247 out->SetScalarType(first->GetScalarType());
2249 first->GetExtent(ext);
2251 out->SetExtent(ext);
2252 // LG : TODO : Z Spacing ?
2254 out->AllocateScalars();
2256 //first->Print(std::cout);
2257 // out->Print(std::cout);
2260 first->GetDimensions(dim);
2261 unsigned long imsize =
2262 ( (unsigned long)first->GetScalarPointer(0,1,0)
2263 - (unsigned long)first->GetScalarPointer(0,0,0))
2267 std::vector<DicomNode*>::iterator it;
2268 for (it=im.begin(); it!=im.end(); ++it)
2270 //std::cout << "copying slice "<<slice <<std::endl;
2271 vtkImageData* cur = mReader.GetImage( (*it)->ImageGetFullFileName() );
2273 void* src = cur->GetScalarPointer(0,0,0);
2274 void* dst = out->GetScalarPointer(0,0,slice);
2275 // std::cout << "src="<<src<<std::endl;
2276 // std::cout << "dst="<<dst<<std::endl;
2277 // std::cout << "siz="<<imsize<<std::endl;
2278 memcpy(dst,src,imsize);
2283 for (ii=1;ii<4;ii++) {
2284 for (jj=1;jj<4;jj++) {
2285 int x = (int)(ii*dim[0] / 4);
2286 int y = (int)(jj*dim[1] / 4);
2287 std::cout << cur->GetScalarComponentAsFloat(x,y,0,0)
2289 << out->GetScalarComponentAsFloat(x,y,slice,0)
2302 std::vector<DicomNode*>::iterator it;
2303 for (it=im.begin(); it!=im.end(); ++it)
2305 vtkImageData* out = vtkImageData::New();
2306 out->ShallowCopy(mReader.GetImage((*it)->ImageGetFullFileName()));
2312 //================================================================
2315 //================================================================
2316 void WxGimmick::GetSelectedDicomNodes(std::vector<DicomNode*>& f)
2318 wxArrayTreeItemIds id;
2319 // TO DO : TEST THAT STYLE IS MULTIPLE
2320 unsigned int nb = mTreeListCtrl->GetSelections(id);
2322 for (unsigned int i=0; i<nb; ++i)
2324 TreeItemData *data =
2325 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2326 if ((data) && (data->IsDicomNode()))
2328 f.push_back ( data->GetDicomNode() );
2332 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2334 f.push_back ( data->GetDicomNode() ); //->ImageGetFullFileName() );
2336 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2338 DicomNode::ChildrenListType::iterator j;
2339 for (j =data->GetDicomNode()->GetChildrenList().begin();
2340 j!=data->GetDicomNode()->GetChildrenList().end();
2343 f.push_back((*j)); //->ImageGetFullFileName() ); }
2349 //================================================================
2351 //================================================================
2352 void WxGimmick::GetSelectedItems(std::vector<wxTreeItemId>& f)
2354 wxArrayTreeItemIds id;
2355 // TO DO : TEST THAT STYLE IS MULTIPLE
2356 unsigned int nb = mTreeListCtrl->GetSelections(id);
2358 for (unsigned int i=0; i<nb; ++i)
2363 //================================================================
2365 //================================================================
2366 DicomNode* WxGimmick::GetDicomNodeOfItem(const wxTreeItemId& i)
2368 TreeItemData *data =
2369 (TreeItemData *)mTreeListCtrl->GetItemData(i);
2370 if (data) return ( data->GetDicomNode() );
2373 //================================================================
2375 //================================================================
2376 //================================================================
2377 //================================================================
2378 //================================================================
2394 //================================================================
2395 //================================================================
2396 //================================================================
2397 //================================================================
2399 BEGIN_EVENT_TABLE(WxGimmick, wxPanel)
2401 EVT_MENU(PopUp_NewCollection,WxGimmick::OnPopUpNewCollection)
2402 EVT_MENU(PopUp_OpenCollection,WxGimmick::OnPopUpOpenCollection)
2403 EVT_MENU(PopUp_CloseCollection,WxGimmick::OnPopUpCloseCollection)
2404 EVT_MENU(PopUp_DeleteCollection,WxGimmick::OnPopUpDeleteCollection)
2405 EVT_MENU(PopUp_AddFile, WxGimmick::OnPopUpAddFile)
2406 EVT_MENU(PopUp_AddRawFile, WxGimmick::OnPopUpAddRawFile)
2407 EVT_MENU(PopUp_AddDirectory, WxGimmick::OnPopUpAddDirectory)
2408 EVT_MENU(PopUp_Remove, WxGimmick::OnPopUpRemove)
2409 EVT_MENU(PopUp_About, WxGimmick::OnPopUpAbout)
2410 EVT_MENU(PopUp_Settings, WxGimmick::OnPopUpSettings)
2412 EVT_MENU_RANGE(PopUp_Sort, PopUp_Sort+99, WxGimmick::OnPopUpSort)
2413 EVT_MENU_RANGE(PopUp_User, PopUp_User+99, WxGimmick::OnPopUpUser)
2418 EVT_TREE_BEGIN_DRAG(TreeListCtrlId, WxGimmick::OnBeginDrag)
2419 EVT_TREE_BEGIN_RDRAG(TreeListCtrlId, WxGimmick::OnBeginRDrag)
2420 EVT_TREE_END_DRAG(TreeListCtrlId, WxGimmick::OnEndDrag)
2423 EVT_TREE_BEGIN_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnBeginLabelEdit)
2424 EVT_TREE_END_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnEndLabelEdit)
2427 EVT_TREE_DELETE_ITEM(TreeListCtrlId, WxGimmick::OnDeleteItem)
2428 #if 0 // there are so many of those that logging them causes flicker
2429 EVT_TREE_GET_INFO(TreeListCtrlId, WxGimmick::OnGetInfo)
2432 EVT_TREE_SET_INFO(TreeListCtrlId, WxGimmick::OnSetInfo)
2435 EVT_TREE_ITEM_EXPANDED(TreeListCtrlId, WxGimmick::OnItemExpanded)
2436 EVT_TREE_ITEM_EXPANDING(TreeListCtrlId, WxGimmick::OnItemExpanding)
2437 EVT_TREE_ITEM_COLLAPSED(TreeListCtrlId, WxGimmick::OnItemCollapsed)
2438 EVT_TREE_ITEM_COLLAPSING(TreeListCtrlId, WxGimmick::OnItemCollapsing)
2441 EVT_TREE_SEL_CHANGED(TreeListCtrlId, WxGimmick::OnSelChanged)
2442 EVT_TREE_SEL_CHANGING(TreeListCtrlId, WxGimmick::OnSelChanging)
2444 EVT_TREE_KEY_DOWN(TreeListCtrlId, WxGimmick::OnTreeKeyDown)
2445 // ACTIVATION = DOUBLE CLICK OR ENTER ON SELECTED
2446 EVT_TREE_ITEM_ACTIVATED(TreeListCtrlId, WxGimmick::OnItemActivated)
2448 // so many differents ways to handle right mouse button clicks...
2449 // EVT_CONTEXT_MENU(WxGimmick::OnContextMenu)
2450 // EVT_TREE_ITEM_MENU is the preferred event for creating context menus
2451 // on a tree control, because it includes the point of the click or item,
2452 // meaning that no additional placement calculations are required.
2453 // EVT_TREE_ITEM_MENU(TreeListCtrlId, WxGimmick::OnItemMenu)
2455 EVT_TREE_ITEM_RIGHT_CLICK(TreeListCtrlId, WxGimmick::OnItemRightClick)
2458 // EVT_RIGHT_DOWN(WxGimmick::OnRMouseDown)
2459 // EVT_RIGHT_UP(WxGimmick::OnRMouseUp)
2460 // EVT_RIGHT_DCLICK(WxGimmick::OnRMouseDClick)
2463 //IMPLEMENT_DYNAMIC_CLASS(WxGimmick, wxTreeListCtrl)
2466 wxTree::wxTree(wxWindow *parent, const wxWindowID id,
2467 const wxPoint& pos, const wxSize& size,
2469 : wxTreeListCtrl(parent, id, pos, size, style)
2471 m_reverseSort = false;
2475 // Add some items to the tree
2476 AddTestItemsToTree(5, 2);
2482 #if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
2483 void WxGimmick::CreateButtonsImageList(int size)
2488 mTreeListCtrl->SetButtonsImageList(NULL);
2492 // Make an image list containing small icons
2493 wxImageList *images = new wxImageList(size, size, true);
2495 // should correspond to TreeListCtrlIcon_xxx enum
2498 icons[0] = wxIcon(icon3_xpm); // closed
2499 icons[1] = wxIcon(icon3_xpm); // closed, selected
2500 icons[2] = wxIcon(icon5_xpm); // open
2501 icons[3] = wxIcon(icon5_xpm); // open, selected
2503 for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
2505 int sizeOrig = icons[i].GetWidth();
2506 if ( size == sizeOrig )
2508 images->Add(icons[i]);
2512 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
2516 mTreeListCtrl->AssignButtonsImageList(images);
2519 void WxGimmick::CreateButtonsImageList(int WXUNUSED(size))
2525 int WxGimmick::OnCompareItems(const wxTreeItemId& item1,
2526 const wxTreeItemId& item2)
2528 if ( m_reverseSort )
2530 // just exchange 1st and 2nd items
2531 return mTreeListCtrl->OnCompareItems(item2, item1);
2535 return mTreeListCtrl->OnCompareItems(item1, item2);
2540 void WxGimmick::DoToggleIcon(const wxTreeItemId& item)
2543 int image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_Folder)
2546 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Normal);
2548 image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_FolderSelected)
2549 ? TreeIcon_FileSelected
2550 : TreeIcon_FolderSelected;
2551 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Selected);
2554 void WxGimmick::LogEvent(const wxChar *name, const wxTreeEvent& event)
2556 wxTreeItemId item = event.GetItem();
2559 text << _T('"') << mTreeListCtrl->GetItemText(item).c_str() << _T('"');
2561 text = _T("invalid item");
2562 // wxLogMessage(wxT("%s(%s)"), name, text.c_str());
2567 #define TREE_EVENT_HANDLER(name) \
2568 void WxGimmick::name(wxTreeEvent& event) \
2570 /* LogEvent(_T(#name), event); */ \
2571 /* SetLastItem(mTreeListCtrl->wxTreeItemId()) *;*/ \
2575 TREE_EVENT_HANDLER(OnBeginRDrag)
2576 TREE_EVENT_HANDLER(OnDeleteItem)
2577 TREE_EVENT_HANDLER(OnGetInfo)
2578 TREE_EVENT_HANDLER(OnSetInfo)
2579 //TREE_EVENT_HANDLER(OnItemExpanded)
2580 TREE_EVENT_HANDLER(OnItemExpanding)
2581 //TREE_EVENT_HANDLER(OnItemCollapsed)
2582 //TREE_EVENT_HANDLER(OnSelChanged)
2583 // TREE_EVENT_HANDLER(OnSelChanging)
2586 void WxGimmick::OnItemCollapsed(wxTreeEvent& event)
2588 // std::cout << "* Collapsed *"<<std::endl;
2591 #undef TREE_EVENT_HANDLER
2593 void WxGimmick::OnTreeKeyDown(wxTreeEvent& event)
2596 // LogKeyEvent(wxT("Tree key down "), event.GetKeyEvent());
2597 std::cout << "* Key down *"<<std::endl;
2598 if (event.GetKeyCode()==WXK_RIGHT)
2600 std::cout << "Right"<<std::endl;
2601 wxTreeItemId itemId = mTreeListCtrl->GetSelection();
2604 std::cout << "item is ok"<<std::endl;
2605 wxPoint clientpt = event.GetPoint();
2606 wxPoint screenpt = ClientToScreen(clientpt);
2607 ShowMenu(itemId, clientpt);
2612 std::cout << "NOT Right"<<std::endl;
2617 void WxGimmick::OnBeginDrag(wxTreeEvent& event)
2619 wxTreeItemId id = event.GetItem();
2620 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2621 // std::cout << "OnBeginDrag("<<id<<")"<<std::endl;
2622 if (data->IsDatabase())
2624 // std::cout << "-- IS ROOT"<<std::endl;
2627 else if (data->IsDicomNode())
2629 // std::cout << "-- IS NODE"<<std::endl;
2632 // need to explicitly allow drag
2633 if ( event.GetItem() != GetDatabaseItem() )
2635 m_draggedItem = event.GetItem();
2637 wxPoint clientpt = event.GetPoint();
2638 wxPoint screenpt = ClientToScreen(clientpt);
2640 wxLogMessage(wxT("OnBeginDrag: started dragging %s at screen coords (%i,%i)"),
2641 GetItemText(m_draggedItem).c_str(),
2642 screenpt.x, screenpt.y);
2648 wxLogMessage(wxT("OnBeginDrag: this item can't be dragged."));
2653 void WxGimmick::OnEndDrag(wxTreeEvent& event)
2655 wxTreeItemId id = event.GetItem();
2656 // std::cout << "OnEndDrag("<<id<<")"<<std::endl;
2657 if (!id.IsOk()) return;
2658 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2659 if (data->IsDatabase())
2661 // std::cout << "-- IS ROOT"<<std::endl;
2663 else if (data->IsDicomNode())
2665 // std::cout << "-- IS NODE"<<std::endl;
2669 wxTreeItemId itemSrc = m_draggedItem,
2670 itemDst = event.GetItem();
2671 m_draggedItem = (wxTreeItemId)0l;
2673 // where to copy the item?
2674 if ( itemDst.IsOk() && !ItemHasChildren(itemDst) )
2676 // copy to the parent then
2677 itemDst = GetItemParent(itemDst);
2680 if ( !itemDst.IsOk() )
2682 wxLogMessage(wxT("OnEndDrag: can't drop here."));
2687 wxString text = GetItemText(itemSrc);
2688 wxLogMessage(wxT("OnEndDrag: '%s' copied to '%s'."),
2689 text.c_str(), GetItemText(itemDst).c_str());
2691 // just do append here - we could also insert it just before/after the item
2692 // on which it was dropped, but this requires slightly more work... we also
2693 // completely ignore the client data and icon of the old item but could
2694 // copy them as well.
2696 // Finally, we only copy one item here but we might copy the entire tree if
2697 // we were dragging a folder.
2698 int image = wxGetApp().ShowImages() ? TreeIcon_File : -1;
2699 AppendItem(itemDst, text, image);
2704 //====================================================================
2705 void WxGimmick::OnBeginLabelEdit(wxTreeEvent& event)
2707 // std::cout << "OnBeginLabelEdit"<<std::endl;
2708 wxTreeItemId id = event.GetItem();
2709 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2710 // If not a root : veto
2711 if (data->IsDatabase())
2718 //====================================================================
2720 //====================================================================
2721 void WxGimmick::OnEndLabelEdit(wxTreeEvent& event)
2723 // std::cout << "OnEndLabelEdit"<<std::endl;
2724 wxTreeItemId id = event.GetItem();
2725 TreeItemData *data = GetItemData(id);
2726 // If not a database : bug !
2727 if (data->IsDatabase())
2729 data->GetDicomNode()->GetDicomDatabase()->SetName(wx2std(event.GetLabel()));
2730 mFieldsView->UpdateValues(data->GetDicomNode());
2734 std::cerr<< "!!!! Internal error : send bug report !!!!"<<std::endl;
2737 //====================================================================
2740 void WxGimmick::OnItemCollapsing(wxTreeEvent& event)
2742 // wxLogMessage(wxT("OnItemCollapsing"));
2744 // for testing, prevent the user from collapsing the first child folder
2745 wxTreeItemId itemId = event.GetItem();
2748 if ( IsTestItem(itemId) )
2750 wxMessageBox(wxT("You can't collapse this item."));
2758 //====================================================================
2759 void WxGimmick::ShowHelp()
2763 mHelpWindow = new WxGimmickHelpWindow(this);
2765 mHelpWindow->CenterOnParent();
2766 mHelpWindow->ShowModal();
2768 //====================================================================
2774 //================================================================
2775 //================================================================
2776 //================================================================
2777 //================================================================
2778 //================================================================
2780 //================================================================
2781 //================================================================
2782 //================================================================
2783 //================================================================
2784 //================================================================
2790 // ----------------------------------------------------------------------------
2792 // ----------------------------------------------------------------------------
2794 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_DRAG)
2795 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_RDRAG)
2796 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_DELETE_ITEM)
2797 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_GET_INFO)
2798 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SET_INFO)
2799 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDED)
2800 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDING)
2801 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSED)
2802 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSING)
2805 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT)
2806 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_LABEL_EDIT)
2809 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED)
2810 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGING)
2811 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_KEY_DOWN)
2812 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU)
2813 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_ITEM_STYLE_CHANGED)
2815 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_ACTIVATED)
2816 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK)
2817 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK)
2818 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_DRAG)
2819 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK)
2820 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP)
2821 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MENU)
2823 // ----------------------------------------------------------------------------
2825 // ----------------------------------------------------------------------------
2827 IMPLEMENT_ABSTRACT_CLASS(WxGimmickEvent, wxNotifyEvent)
2830 WxGimmickEvent::WxGimmickEvent(wxEventType commandType,
2832 const wxTreeItemId& item)
2834 wxNotifyEvent(commandType, tree->GetId()),
2838 // m_editCancelled = false;
2840 SetEventObject(tree);
2843 SetClientObject(tree->mTreeListCtrl->GetItemData(item));
2846 WxGimmickEvent::WxGimmickEvent(wxEventType commandType, int id)
2848 wxNotifyEvent(commandType, id),
2852 // m_editCancelled = false;
2855 WxGimmickEvent::WxGimmickEvent(const WxGimmickEvent & event)
2857 wxNotifyEvent(event),
2861 m_evtKey = event.m_evtKey;
2862 m_item = event.m_item;
2863 m_itemOld = event.m_itemOld;
2864 mColor = event.mColor;
2865 mUserData = event.mUserData;
2866 // m_pointDrag = event.m_pointDrag;
2867 // m_label = event.m_label;
2868 // m_editCancelled = event.m_editCancelled;
2878 //================================================================
2879 //================================================================
2880 //================================================================
2881 //================================================================
2882 //================================================================
2883 WxGimmickFrame::WxGimmickFrame( wxWindow *parent,
2886 : wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size)
2888 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
2889 mWxGimmick = new WxGimmick(this,-1,
2892 sizer->Add(mWxGimmick,1,wxGROW);
2894 SetAutoLayout(true);
2897 //================================================================
2899 //================================================================
2900 WxGimmickFrame::~WxGimmickFrame()
2903 //================================================================
2905 //================================================================
2906 void WxGimmickFrame::OnSelChanged(WxGimmickEvent& event)
2908 // std::cout << "+++++ WxGimmickFrame::OnSelChanged ++++++++++"
2910 std::vector<std::string> file;
2911 // mWxGimmick->GetSelectedImages(file);
2913 std::vector<std::string>::iterator i;
2914 for (i=file.begin();i!=file.end();++i)
2916 std::cout << "'" << *i << "'" << std::endl;
2918 std::cout << "++++++++++++++++++++" << std::endl;
2921 //================================================================
2923 //================================================================
2924 BEGIN_EVENT_TABLE(WxGimmickFrame, wxFrame)
2925 EVT_TREEVIEWLIST_SEL_CHANGED(-1,WxGimmickFrame::OnSelChanged)
2927 //================================================================