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 PopUp_AddToFavorites = 702
69 //================================================================
71 //================================================================
72 #define TreeListCtrlId 10000
73 //================================================================
75 //================================================================
76 const icon_id Icon[5] = { Icon_Database,
81 //================================================================
84 //================================================================
85 class WxGimmickDicomNodeData : public DicomNodeData
88 WxGimmickDicomNodeData
89 (WxGimmickTreeItemData* d = 0) :
93 ~WxGimmickDicomNodeData();
95 WxGimmickTreeItemData* GetTreeItemData()
96 { return mTreeItemData; }
97 void SetTreeItemData( WxGimmickTreeItemData* d)
98 { mTreeItemData = d; }
99 inline bool IsLoaded() { return mLoaded; }
100 inline void SetLoaded(bool v) { mLoaded = v; }
103 WxGimmickTreeItemData* mTreeItemData;
106 //================================================================
109 //================================================================
110 class WxGimmickTreeItemData : public wxTreeItemData
113 WxGimmickTreeItemData(DicomNode* node)
123 WxGimmickDicomNodeData* data =
124 node->GetData<WxGimmickDicomNodeData*>();
127 if (data->GetTreeItemData()!=0)
129 std::cout << "WxGimmickTreeItemData ERROR ****"
133 data->SetTreeItemData(this);
136 node->SetData( new WxGimmickDicomNodeData(this) );
137 if (node->GetType()==DicomNode::Database)
147 ~WxGimmickTreeItemData()
151 WxGimmickDicomNodeData* data =
152 mDicomNode->GetData<WxGimmickDicomNodeData*>();
153 if (data) data->SetTreeItemData(0);
157 inline void ResetDicomNode()
162 inline void SetItemId ( const wxTreeItemId& item ) { mItemId = item; }
163 inline const wxTreeItemId& GetItemId() const { return mItemId; }
165 inline bool IsDefault() const { return (mType == 0); }
166 inline bool IsDatabase() const { return (mType == 2); }
167 inline bool IsDicomNode() const { return (mType == 1); }
169 inline DicomNode* GetDicomNode() { return mDicomNode; }
170 inline long& UpdateTime() { return mUpdateTime; }
171 inline bool IsLoaded()
173 mDicomNode->GetData<WxGimmickDicomNodeData*>()->IsLoaded();
175 inline void SetLoaded(bool v)
177 mDicomNode->GetData<WxGimmickDicomNodeData*>()->SetLoaded(v);
180 inline int GetUserFlags() const { return mUserFlags; }
181 inline void SetUserFlags(int f) { mUserFlags = f; }
184 // The type of item :
187 // 2 = DicomNode of type Database
189 wxTreeItemId mItemId;
190 DicomNode* mDicomNode;
195 //================================================================
198 //================================================================
199 WxGimmickDicomNodeData::~WxGimmickDicomNodeData()
203 mTreeItemData->ResetDicomNode();
206 //================================================================
241 //================================================================
242 //================================================================
243 //================================================================
244 //================================================================
245 //================================================================
246 //================================================================
247 //================================================================
248 WxGimmick::WxGimmick(wxWindow *parent,
254 : wxPanel(parent,id,pos,size),
255 mSelectionType(image_type),
256 mSaveConfigurationOnClose(true),
259 // Initialize image size corresponding to current selection
260 switch (mSelectionType)
262 case GIMMICK_2D_IMAGE_SELECTION : mSelectionMaxImageDimension = 2; break;
263 case GIMMICK_3D_IMAGE_SELECTION : mSelectionMaxImageDimension = 3; break;
264 case GIMMICK_4D_IMAGE_SELECTION : mSelectionMaxImageDimension = 4; break;
265 default : mSelectionMaxImageDimension = 0;
269 // Start the threads ...
273 SetDatabaseExtension("sqlite3");
274 // Create the UserSettings dir if does not exist
275 CreateUserSettingsDirectory();
276 // Sets the current directory to the Setting dir
277 mCurrentDirectory = std2wx(GetUserSettingsDirectory());
279 // Window layout creation
280 wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
283 mSplitter1 = new wxSplitterWindow( this, -1);
285 // TreeCtrl on the left
290 //| wxTR_LINES_AT_ROOT
291 | wxTR_FULL_ROW_HIGHLIGHT
298 | wxTR_EDIT_LABELS //Use this style if you wish the user to be able to edit labels in the tree list control.
299 //wxTR_NO_BUTTONS For convenience to document that no buttons are to be drawn.
300 | wxTR_HAS_BUTTONS //Use this style to show + and - buttons to the left of parent items.
301 | 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.
302 //wxTR_NO_LINES Use this style to hide vertical level connectors.
303 | 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.)
304 | 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.
305 | 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.
306 // wxTR_ROW_LINES // Use this style to draw a contrasting border between displayed rows.
307 // 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.
308 // 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.
309 | 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.
310 | wxTR_EXTENDED // Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases.)
311 //wxTR_DEFAULT_STYLE The set of flags that are closest to the defaults for the native control for a particular toolkit.
312 //| wxTR_VIRTUAL //The application provides items text on demand.
315 mTreeListCtrl = new wxTreeListCtrl(mSplitter1,
321 mTreeListCtrl->SetIndent(0);
322 mTreeListCtrl->SetLineSpacing(5);
327 wxPanel *rpanel = new wxPanel( mSplitter1, -1 );
329 wxBoxSizer *rsizer = new wxBoxSizer(wxHORIZONTAL);
330 // Right panel top/bottom split
331 mSplitter2 = new wxSplitterWindow( rpanel , -1);
334 mPanelImage = new wxPanel(mSplitter2,-1);
335 mPanelImage->SetBackgroundColour( wxColour(0,0,0) );
337 wxBoxSizer *isizer = new wxBoxSizer(wxHORIZONTAL );
338 mPanelImage->SetSizer( isizer );
341 mwxNotebook = new wxNotebook(mSplitter2,
342 -1,wxDefaultPosition, wxDefaultSize, 0);
346 // Fields view (bottom)
347 mFieldsView = new WxGimmickFieldsView(mwxNotebook,-1,
351 mFieldsView->SetColors
352 ( GetSettings().Colour(DicomNode::Database),
353 GetSettings().BgColour(DicomNode::Database),
354 GetSettings().Colour(DicomNode::Patient),
355 GetSettings().BgColour(DicomNode::Patient),
356 GetSettings().Colour(DicomNode::Study),
357 GetSettings().BgColour(DicomNode::Study),
358 GetSettings().Colour(DicomNode::Series),
359 GetSettings().BgColour(DicomNode::Series),
360 GetSettings().Colour(DicomNode::Image),
361 GetSettings().BgColour(DicomNode::Image));
362 mwxNotebook->AddPage( mFieldsView, _T("Dicom fields"));
365 mHelp = new WxGimmickHelp(mwxNotebook);
366 mwxNotebook->AddPage( mHelp, _T("Help"));
369 int wsize = size.GetWidth();
370 int hsize = size.GetHeight();
371 int previewhsize = 150;
372 int previewwsize = 400;
374 mSplitter2->SetMinimumPaneSize( previewhsize );
375 mSplitter2->SplitHorizontally( mPanelImage, mwxNotebook, //mFieldsView,
376 hsize - previewhsize);
378 rsizer->Add( mSplitter2,1,wxGROW ,0);
380 rpanel->SetAutoLayout(true);
381 rpanel->SetSizer( rsizer );
385 mInteractor = new crea::creawxVTKRenderWindowInteractor(mPanelImage,-1);
386 mInteractor->UseCaptureMouseOn();
388 mViewer = vtkImageViewer2::New();
389 mViewer->SetupInteractor ( mInteractor );
390 mViewer->SetInput(mReader.GetImage(""));
392 isizer-> Add( mInteractor ,1,wxGROW ,0);
394 topsizer->Add( mSplitter1,1,wxGROW ,0);
397 mSplitter1->SetMinimumPaneSize( 200 );
398 mSplitter1->SplitVertically(mTreeListCtrl,
400 wsize - previewwsize );
403 // ProcessImageEvents();
404 SetSizer( topsizer );
407 mDatabaseListFile = GetUserSettingsDirectory();
408 mDatabaseListFile += "collections.txt";
413 ShowImage(mReader.GetImage(""));
415 // Show help if no collection
416 if (GetDicomDatabaseList().size()==0)
418 mwxNotebook->SetSelection(1);
422 mwxNotebook->SetSelection(0);
424 // mJustStarted = true;
426 //================================================================
430 #define VALID_FILE_SEPARATOR "\\"
431 #define INVALID_FILE_SEPARATOR "/"
433 #define INVALID_FILE_SEPARATOR "\\"
434 #define VALID_FILE_SEPARATOR "/"
437 //================================================================
438 const std::string& WxGimmick::GetUserSettingsDirectory()
440 if (mUserSettingsDirectory.size()==0)
442 #if defined(__GNUC__)
443 mUserSettingsDirectory = getenv("HOME");
444 #elif defined(_WIN32)
445 mUserSettingsDirectory = getenv("USERPROFILE");
447 mUserSettingsDirectory += "/.gimmick/";
448 boost::algorithm::replace_all( mUserSettingsDirectory,
449 INVALID_FILE_SEPARATOR ,
450 VALID_FILE_SEPARATOR);
452 return mUserSettingsDirectory;
454 //================================================================
456 //========================================================================
457 void WxGimmick::CreateUserSettingsDirectory()
459 if (! boost::filesystem::is_directory( GetUserSettingsDirectory() ) )
461 creaMessage("Gimmick!",1,"==> Directory '"<<GetUserSettingsDirectory()<<"' "
462 << "does not exist : creating it"<<std::endl);
464 if ( ! boost::filesystem::create_directory( GetUserSettingsDirectory() ) )
466 creaMessage("Gimmick!",1,"!! ERROR CREATING '"<<GetUserSettingsDirectory()<<"'");
470 //========================================================================
472 //================================================================
473 WxGimmick::~WxGimmick()
475 // std::cout << "WxGimmick::~WxGimmick()" <<std::endl;
476 if (mSaveConfigurationOnClose) SaveConfiguration();
479 // std::cout << "Reader stopped"<<std::endl;
481 DicomDatabaseListType::iterator i;
482 for (i =GetDicomDatabaseList().begin();
483 i!=GetDicomDatabaseList().end();
491 //================================================================
494 //================================================================
495 void WxGimmick::RebuildView()
499 mTreeListCtrl->DeleteRoot(); //DeleteAllItems();
500 // mTreeDefaultItemId = wxTreeItemId();
503 int nbattr = mSettings.GetMaxNumberOfColumns();
505 for (int j=0;j<nbattr; j++)
507 mTreeListCtrl->AddColumn (_T(""),
508 200, //DEFAULT_COL_WIDTH,
514 mTreeListCtrl->SetMainColumn (0);
515 mTreeListCtrl->SetColumnEditable (0, true);
517 mTreeRootId = mTreeListCtrl->AddRoot( _T(""),Icon_Root,Icon_Root);
519 // The collections columns legends
520 mCollectionsTitlesItemId =
521 CreateChildrenColumnsTitles(mTreeRootId,DicomNode::Database);
523 DicomDatabaseListType::iterator i;
524 for (i =GetDicomDatabaseList().begin();
525 i!=GetDicomDatabaseList().end();
528 UpdateDicomDatabaseView(*i);
531 mTreeListCtrl->Expand(mTreeRootId);
533 // mTreeListCtrl->ExpandAll(mTreeRootId);
534 // std::cout << "EO RebuildAll"<<std::endl;
536 //================================================================
540 //================================================================
541 void WxGimmick::UpdateDicomDatabaseView(DicomDatabase* db)
547 // Does the db exist ?
548 wxTreeItemIdValue cookie;
549 for (dbid = mTreeListCtrl->GetFirstChild(mTreeRootId,cookie);
551 dbid = mTreeListCtrl->GetNextChild(mTreeRootId,cookie))
553 data = (TreeItemData *)mTreeListCtrl->GetItemData(dbid);
554 if ((data->IsDatabase())&&(data->GetDicomNode()==db)) break;
557 // Not found : create
561 int iconid = Icon[DicomNode::Database];
564 // std::cout << " -> Creating item for '"<<db->GetLabel()<<"'"<<std::endl;
565 data = new TreeItemData(db);
566 dbid = mTreeListCtrl->AppendItem( mTreeRootId,
567 std2wx(db->GetLabel()),
571 data->SetItemId(dbid);
572 mTreeListCtrl->SetItemTextColour
573 (dbid,mSettings.Colour(DicomNode::Database));
574 mTreeListCtrl->SetItemBackgroundColour
575 (dbid,mSettings.BgColour(DicomNode::Database));
577 // The patients columns legends
578 CreateChildrenColumnsTitles(dbid,DicomNode::Patient);
581 // Increase UpdateTime to detect obsolete items after
583 data->UpdateTime()++;
585 DicomNode::ChildrenListType::iterator j;
586 for (j= db->GetChildrenList().begin();
587 j!=db->GetChildrenList().end();
590 UpdateDicomNodeView(*j,dbid);
593 DeleteObsoleteChildren(dbid);
595 mTreeListCtrl->EnsureVisible(dbid);
598 //================================================================
600 //================================================================
601 void WxGimmick::UpdateDicomNodeView(DicomNode* n,
602 const wxTreeItemId& parent)
606 // std::cout << "* UpdateDicomNodeView("<<n->GetLabel()<<")"<<std::endl;
608 wxTreeItemId newparent = parent;
611 if ((!mSettings.MergeStudySeries()) ||
612 (n->GetType() != DicomNode::Study))
614 // Does the item exist ?
615 wxTreeItemIdValue cookie;
616 for (newparent = mTreeListCtrl->GetFirstChild(parent,cookie);
618 newparent = mTreeListCtrl->GetNextChild(parent,cookie))
620 data = (TreeItemData *)mTreeListCtrl->GetItemData(newparent);
621 if (data->GetDicomNode() == n) break;
623 // Not found : create
624 if (!newparent.IsOk())
626 int image(Icon[n->GetType()]);
627 wxColour *colour(&mSettings.Colour(n->GetType()));
628 wxColour *bgcolour(&mSettings.BgColour(n->GetType()));
630 if (n->GetType()==DicomNode::Image)
632 // std::cout << "!!!Image"<<std::endl;
633 if (n->GetData<NodeData*>()!=0)
635 // std::cout << ">> n->GetData<NodeData*>()!=0" << std::endl;
636 if (n->GetData<NodeData*>()->IsLoaded())
638 colour = &mSettings.LoadedImageColour();
640 // std::cout << "<< n->GetData<NodeData*>()!=0" << std::endl;
644 data = new TreeItemData(n);
645 newparent = mTreeListCtrl->AppendItem(parent,
649 data->SetItemId(newparent);
650 mTreeListCtrl->SetItemTextColour(newparent,*colour);
651 mTreeListCtrl->SetItemBackgroundColour(newparent,*bgcolour);
653 UpdateColumns(newparent);
656 if (n->GetType()!=DicomNode::Image)
658 CreateChildrenColumnsTitles(newparent,n->GetType()+1);
664 UpdateColumns(newparent,true);
667 // synchonise update time with parent
668 TreeItemData * parent_data =
669 (TreeItemData *)mTreeListCtrl->GetItemData(parent);
670 data->UpdateTime() = parent_data->UpdateTime();
673 DicomNode::ChildrenListType::iterator i;
674 for (i=n->GetChildrenList().begin();
675 i!=n->GetChildrenList().end();
678 UpdateDicomNodeView(*i,newparent);
681 if (n->GetType() != DicomNode::Image)
682 DeleteObsoleteChildren(newparent);
685 //================================================================
687 //================================================================
688 void WxGimmick::UpdateColumns(wxTreeItemId& item,
692 (TreeItemData *)mTreeListCtrl->GetItemData(item);
693 DicomNode* node = data->GetDicomNode();
697 // Update only the first field (for #children update)
698 DicomNode* node2 = node;
699 // If Study and Series level are merged and node type is Series
700 // then have to get back to the Study level
701 if ((mSettings.MergeStudySeries())&&
702 (node->GetType() == DicomNode::Series))
703 node2 = node->GetParent();
706 lab += node2->GetFieldValueMap()
707 [ mSettings.GetColumnList(node2->GetType())[0].Key ];
709 if (node->GetType() != DicomNode::Image)
711 if (node->GetChildrenList().size()>0)
714 sprintf(sz," [%d]",node->GetNumberOfChildren());
718 mTreeListCtrl->SetItemText(item,std2wx(lab));
724 Settings::ColumnListType::iterator col;
725 // If Study and Series level are merged and node type is Series
726 // then have to fill the Study level cols first
727 if ((mSettings.MergeStudySeries())&&
728 (node->GetType() == DicomNode::Series))
730 DicomNode* node2 = node->GetParent();
731 for (col = mSettings.GetColumnList(node2->GetType()).begin();
732 col != mSettings.GetColumnList(node2->GetType()).end();
735 std::string s = node2->GetFieldValueMap()[col->Key];
740 sprintf(sz," [%d]",node->GetNumberOfChildren());
743 mTreeListCtrl->SetItemText (item, c, std2wx(s));
748 for (col = mSettings.GetColumnList(node->GetType()).begin();
749 col != mSettings.GetColumnList(node->GetType()).end();
752 std::string s = node->GetFieldValueMap()[col->Key];
753 if ((c==0)&&(node->GetType() != DicomNode::Image))
756 sprintf(sz," [%d]",node->GetNumberOfChildren());
759 mTreeListCtrl->SetItemText (item, c, std2wx(s));
765 //================================================================
767 //================================================================
768 wxTreeItemId WxGimmick::CreateChildrenColumnsTitles
772 // Creates the sub-level columns titles
774 = new TreeItemData(0);
775 wxTreeItemId id = mTreeListCtrl->AppendItem( item,
781 mTreeListCtrl->SetItemFont(id, *wxITALIC_FONT);
782 mTreeListCtrl->SetItemTextColour(id, mSettings.Colour(t));
783 mTreeListCtrl->SetItemBackgroundColour(id, mSettings.BgColour(t));
784 UpdateColumnsTitles(id,t);
787 //================================================================
789 //================================================================
790 void WxGimmick::UpdateColumnsTitles(wxTreeItemId& item,
793 // std::cout << "Update columns titles "<<t<<std::endl;
795 Settings::ColumnListType::iterator col;
796 for (col = mSettings.GetColumnList(t).begin();
797 col != mSettings.GetColumnList(t).end();
800 // std::cout << col->Name << std::endl;
801 mTreeListCtrl->SetItemText (item, c, std2wx(col->Name));
805 //================================================================
808 //================================================================
809 void WxGimmick::DeleteObsoleteChildren(wxTreeItemId& id)
812 TreeItemData * parent_data =
813 (TreeItemData *)mTreeListCtrl->GetItemData(id);
816 wxTreeItemIdValue cookie;
817 std::vector<wxTreeItemId> children;
818 for (child = mTreeListCtrl->GetFirstChild(id,cookie);
820 child = mTreeListCtrl->GetNextChild(id,cookie))
822 children.push_back(child);
824 std::vector<wxTreeItemId>::iterator i;
825 for (i=children.begin();i!=children.end();++i)
828 (TreeItemData *)mTreeListCtrl->GetItemData(*i);
830 ((data->GetDicomNode()>0) &&
831 ((data->UpdateTime() != parent_data->UpdateTime()))) ||
832 ((data->IsDicomNode()) &&
833 (data->GetDicomNode()==0))
836 // std::cout << "DOBSC="<<mTreeListCtrl->GetItemText(*i)<<std::endl;
837 mTreeListCtrl->Delete(*i);
841 //================================================================
843 //================================================================
844 void WxGimmick::OpenOrNewDatabase(bool open)
848 long style = wxFD_SAVE | wxFD_OVERWRITE_PROMPT;
849 if (open) style = wxOPEN | wxFILE_MUST_EXIST;
850 std::string wc("*.");
851 wc += GetDatabaseExtension();
853 // TO DO : Handler give their wildcards
854 wxFileDialog* FD = new wxFileDialog( 0,
862 if (FD->ShowModal()!=wxID_OK) return;
864 std::string filename = wx2std (FD->GetPath());
865 mCurrentDirectory = FD->GetDirectory();
869 boost::filesystem::path filepath(filename);
870 boost::filesystem::change_extension(filepath,GetDatabaseExtension());
871 if ( boost::filesystem::exists(filepath) )
873 boost::filesystem::remove(filepath);
875 LG : works on Linux but not Windows :
876 if ( ! boost::filesystem::remove(filepath) )
878 wxMessageBox(_T("Could not overwrite ")
879 +std2wx(filepath.string()),
890 DicomDatabase* db = new DicomDatabase(filename);
897 wxMessageBox(_T("An error occured while opening ")
907 wxGetTextFromUser(_T("Enter collection name"),_T("New collection"),
909 db->SetName(wx2std(collname));
914 wxMessageBox(_T("An error occured while creating ")
922 if (GetDicomDatabaseList().size()==0) mFieldsView->UpdateFields(db);
923 GetDicomDatabaseList().push_back(db);
924 UpdateDicomDatabaseView(db);
928 //================================================================
931 //================================================================
932 void WxGimmick::LoadConfiguration()
935 // std::cout << "WxGimmick : Reading config"<<std::endl;
936 LoadOrCreateFavoritesDatabase();
939 creaMessage("Gimmick!",1,"Gimmick! : ==> Loading collections from '"<<mDatabaseListFile<<"'"<<std::endl);
944 s.open(mDatabaseListFile.c_str());
951 if (str.size()==0) continue;
953 std::vector<std::string> tokens;
954 boost::split( tokens, str, boost::is_any_of("\t") );
956 DicomDatabase* db = new DicomDatabase(tokens[0]);
958 // std::cout << " -> Loading collection '"<<tokens[0]<<"'"<<std::endl;
960 if (tokens.size()==2)
962 db->SetName(tokens[1]);
967 GetDicomDatabaseList().push_back(db);
968 db->DBLoadChildren(db,DicomNode::Patient);
969 if (mSettings.HasActiveComparator(DicomNode::Patient))
972 ( mSettings.GetActiveComparator(DicomNode::Patient) );
977 creaMessage("Gimmick!",1," ==> ERROR opening collection '"<<tokens[0]<<"'"<<std::endl);
985 creaMessage("Gimmick!",1," ==> File does not exist. It will be created on exit (if you already ran Gimmick! and exited normally, this is not normal. Send a bug report).");
989 mTreeListCtrl->SetBackgroundColour(mSettings.BgColour(DicomNode::Database));
990 if (GetDicomDatabaseList().begin() !=
991 GetDicomDatabaseList().end() )
993 mFieldsView->UpdateFields(*GetDicomDatabaseList().begin());
999 //================================================================
1001 //================================================================
1002 void WxGimmick::SaveConfiguration()
1005 creaMessage("Gimmick!",1,"Gimmick! : Saving configuration..."<<std::endl);
1007 creaMessage("Gimmick!",1,"Gimmick! : ==> Saving collections in '"
1008 <<mDatabaseListFile<<"'"<<std::endl);
1011 s.open(mDatabaseListFile.c_str());
1014 creaError("Gimmick! : error opening '"<<mDatabaseListFile<<"'");
1017 DicomDatabaseListType::iterator i;
1018 for (i =GetDicomDatabaseList().begin();
1019 i!=GetDicomDatabaseList().end();
1022 s << (*i)->GetFileName() << "\t";
1023 s << (*i)->GetName() << std::endl;
1029 //================================================================
1031 //================================================================
1032 void WxGimmick::LoadOrCreateFavoritesDatabase()
1036 //================================================================
1039 //================================================================
1040 void WxGimmick::OnClose(wxCloseEvent& event)
1042 if (mSaveConfigurationOnClose) SaveConfiguration();
1044 //================================================================
1046 //================================================================
1047 void WxGimmick::OnItemActivated(wxTreeEvent& event)
1053 // std::cout << "OnItemActivated" <<std::endl;
1054 wxTreeItemId itemId = event.GetItem();
1055 if (mTreeListCtrl->IsExpanded(itemId))
1057 mTreeListCtrl->Collapse(itemId);
1061 mTreeListCtrl->Expand(itemId);
1064 //================================================================
1066 //================================================================
1067 void WxGimmick::LoadChildren(wxTreeItemId& id)
1069 TreeItemData *item = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1072 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1073 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1076 // If children not already loaded : do it
1078 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1079 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1082 // Some new children loaded
1084 if (mSettings.HasActiveComparator
1085 (item->GetDicomNode()->GetType()+1))
1087 /* std::cout << "Sorting using '"
1088 << mSettings.GetActiveComparator
1089 (item->GetDicomNode()->GetType()+1).GetName()
1092 item->GetDicomNode()->SortChildren
1093 ( mSettings.GetActiveComparator
1094 (item->GetDicomNode()->GetType()+1)
1096 // std::cout << "ok"<<std::endl;
1099 DicomNode::ChildrenListType::iterator i;
1100 for (i=item->GetDicomNode()->GetChildrenList().begin();
1101 i!=item->GetDicomNode()->GetChildrenList().end();
1104 UpdateDicomNodeView(*i,id);
1107 // EO If children not already loaded
1111 //================================================================
1114 //================================================================
1115 void WxGimmick::OnItemExpanded(wxTreeEvent& event)
1118 // std::cout << "* Expanded *"<<std::endl;
1123 wxTreeItemId itemId = event.GetItem();
1124 LoadChildren(itemId);
1128 // expand if collapsed and collapse if expanded ...
1129 TreeItemData *item =
1130 (TreeItemData *)mTreeListCtrl->GetItemData(itemId);
1133 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1134 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1137 // If children not already loaded : do it
1139 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1140 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1144 // Some new children loaded
1146 if (mSettings.HasActiveComparator
1147 (item->GetDicomNode()->GetType()+1))
1149 /* std::cout << "Sorting using '"
1150 << mSettings.GetActiveComparator
1151 (item->GetDicomNode()->GetType()+1).GetName()
1154 item->GetDicomNode()->SortChildren
1155 ( mSettings.GetActiveComparator
1156 (item->GetDicomNode()->GetType()+1)
1158 // std::cout << "ok"<<std::endl;
1161 // If images : sort them
1162 if (item->IsDicomNode())
1164 if (item->GetDicomNode()->GetType()==DicomNode::Series)
1168 LexicographicalDicomNodeComparator compare;
1169 // DicomNodeImageImageNumberComparator c1;
1171 DicomNodeImageSliceLocationComparator c1;
1172 DicomNodeImageImageNumberComparator c2;
1173 DicomNodeImageFileNameComparator cn;
1177 // std::cout << "SORT"<<std::endl;
1178 item->GetDicomNode()->SortChildren(compare);
1179 // std::cout << "EO SORT"<<std::endl;
1187 DicomNode::ChildrenListType::iterator i;
1188 for (i=item->GetDicomNode()->GetChildrenList().begin();
1189 i!=item->GetDicomNode()->GetChildrenList().end();
1192 UpdateDicomNodeView(*i,itemId);
1195 // EO If children not already loaded
1198 // mTreeListCtrl->Expand(itemId);
1201 //================================================================
1205 //=====================================================================
1206 void WxGimmick::InsertRoot(wxTreeItemId& id, Root* r)
1209 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1214 data->GetDicomNode()->GetDicomDatabase()->LoadAll();
1215 printf(">>>>>> Time to load all = %ldms \n",sw.Time());
1217 UpdateRootView(data->GetDicomNode()->GetDicomDatabase());
1220 if (data->IsDicomNode())
1223 r->Insert(data->GetDicomNode());
1224 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1227 else if (data->IsDatabase())
1230 DicomNode::ChildrenListType::iterator j;
1231 for (j= data->GetDicomNode()->GetChildrenList().begin();
1232 j!=data->GetDicomNode()->GetChildrenList().end();
1237 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1243 //=====================================================================
1247 //=================================================
1248 void WxGimmick::DeleteDicomDatabase(wxTreeItemId& id,
1252 DicomDatabaseListType::iterator i = find(GetDicomDatabaseList().begin(),
1253 GetDicomDatabaseList().end(),
1256 GetDicomDatabaseList().erase(i);
1257 mTreeListCtrl->Delete(id);
1259 //=================================================
1263 //=====================================================================
1265 void WxGimmick::OnItemRightClick(wxTreeEvent& event)
1268 wxTreeItemId itemId = event.GetItem();
1271 wxPoint clientpt = event.GetPoint();
1272 wxPoint screenpt = ClientToScreen(clientpt);
1273 ShowMenu(itemId, clientpt);
1277 //=====================================================================
1281 //=====================================================================
1282 void WxGimmick::ShowMenu(wxTreeItemId id, const wxPoint& pt)
1285 // std::cout << "ShowMenu" <<std::endl;
1287 TreeItemData *data =
1288 (TreeItemData *)mTreeListCtrl->GetItemData(id);
1294 title << wxT("Menu for ") << mTreeListCtrl->GetItemText(id);
1298 title = wxT("Menu for no particular item");
1305 if (id==mCollectionsTitlesItemId)
1307 menu.Append(PopUp_NewCollection, _T("&New collection"));
1308 menu.Append(PopUp_OpenCollection, _T("&Open collection"));
1312 if (data->IsDatabase())
1314 wxMenu* addmenu = new wxMenu;
1315 addmenu->Append(PopUp_AddDirectory, _T("Scan &Directory"));
1316 addmenu->Append(PopUp_AddFile, _T("Select &File(s)"));
1317 // addmenu->Append(PopUp_AddRawFile, _T("Add &Raw image"));
1318 menu.AppendSubMenu(addmenu, _T("&Add image(s) to collection..."));
1319 menu.Append(PopUp_CloseCollection, _T("&Close collection"));
1320 menu.Append(PopUp_DeleteCollection, _T("&Delete collection"));
1322 if (data->IsDicomNode())
1327 std::string str("&Remove ");
1328 str += data->GetDicomNode()->GetTypeName();
1329 menu.Append(PopUp_Remove, std2wx(str));
1333 if ((data->GetDicomNode()>0)&&
1334 ( data->GetDicomNode()->GetType()<DicomNode::Image))
1336 int ctype = data->GetDicomNode()->GetType()+1;
1337 if (mSettings.HasActiveComparator(ctype))
1339 wxMenu* sortmenu = new wxMenu;
1341 Settings::ComparatorsList::iterator i;
1342 for (i =mSettings.GetComparatorsList(ctype).begin();
1343 i !=mSettings.GetComparatorsList(ctype).end();
1346 sortmenu->AppendRadioItem(PopUp_Sort+n, std2wx(i->GetName()));
1350 sortmenu->Check(PopUp_Sort+
1351 mSettings.GetActiveComparatorIndex(ctype)
1354 std::string sortmenustr("&Sort ");
1355 sortmenustr += DicomNode::GetPluralTypeName(ctype);
1356 sortmenustr += " by...";
1357 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1358 menu.AppendSubMenu(sortmenu,std2wx(sortmenustr));
1361 item->GetDicomNode()->SortChildren
1362 ( mSettings.GetActiveComparator
1363 (item->GetDicomNode()->GetType()+1)
1365 std::cout << "ok"<<std::endl;
1370 // Event : user can customize the menu
1372 ev(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU,this,id);
1376 ev.SetDicomNode(data->GetDicomNode());
1378 GetEventHandler()->ProcessEvent(ev);
1381 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1382 menu.Append(PopUp_Settings, wxT("&Settings..."));
1383 menu.Append(PopUp_About, wxT("&About..."));
1388 wxMenu* newmenu = new wxMenu;
1389 wxMenu* openmenu = new wxMenu;
1390 Tree::RootHandlerListType::iterator h;
1392 for (h= Tree::GetRootHandlerList().begin();
1393 h!=Tree::GetRootHandlerList().end();
1396 if ((*h)->SupportsNew())
1398 newmenu->Append(PopUp_New+i, std2wx((*h)->GetName()));
1400 if ((*h)->SupportsOpen())
1401 openmenu->Append(PopUp_Open+i, std2wx((*h)->GetName()));
1405 menu.AppendSubMenu(openmenu, _T("&Open"));
1406 menu.AppendSubMenu(newmenu, _T("&New"));
1410 if ((data->IsDatabase())||(data->IsDicomNode()))
1412 Root* itroot = data->GetDicomNode()->GetDicomDatabase();
1413 // if (!itroot) itroot = data->GetDicomNode()->GetRoot();
1414 wxMenu* insertmenu = new wxMenu;
1415 bool hasone = false;
1417 Tree::RootListType::iterator j;
1418 for (j = mTree->GetDatabaseList().begin();
1419 j != mTree->GetDatabaseList().end();
1422 // std::cout << (*j)->GetName() << " "
1423 // << (*j)->GetTypeName()
1424 // << " i="<<(*j)->SupportsInsert()<<std::endl;
1425 if ( ((*j)!=itroot) && ((*j)->SupportsInsert()) )
1427 insertmenu->Append(PopUp_Insert+i,
1428 std2wx((*j)->GetName()));
1434 if (hasone) menu.AppendSubMenu(insertmenu, _T("&Insert into"));
1436 if (data->IsDatabase())
1438 menu.Append(PopUp_Close, wxT("&Close"));
1440 if (data->IsDicomNode() && data->GetDicomNode()->GetDicomDatabase()->SupportsRemove())
1442 menu.Append(PopUp_Remove, wxT("&Remove"));
1450 PopupMenu(&menu, pt);
1451 #endif // wxUSE_MENUS
1453 // std::cout << "EO ShowMenu" <<std::endl;
1455 //=====================================================================
1457 //=====================================================================
1458 // Pop up menu callbacks
1459 void WxGimmick::OnPopUpAbout(wxCommandEvent& event)
1461 wxMessageBox( _T("Give me my medical images quick ! \n\n (c) CREATIS-LRMN 2008\n laurent.guigues@creatis.insa-lyon.fr"),
1463 wxOK | wxICON_INFORMATION, this);
1465 //=====================================================================
1467 //=====================================================================
1468 void WxGimmick::OnPopUpSettings(wxCommandEvent& event)
1470 WxGimmickSettingsDialog* s =
1471 new WxGimmickSettingsDialog(this,&mSettings);
1475 //=====================================================================
1477 //=====================================================================
1478 void WxGimmick::OnPopUpNewCollection(wxCommandEvent& event)
1481 OpenOrNewDatabase(false);
1483 //=====================================================================
1487 //=====================================================================
1488 void WxGimmick::OnPopUpOpenCollection(wxCommandEvent& event)
1491 OpenOrNewDatabase(true);
1493 //=====================================================================
1496 //=====================================================================
1497 void WxGimmick::OnPopUpCloseCollection(wxCommandEvent& event)
1499 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;
1502 // std::cout << "OnPopUpClose"<<std::endl;
1503 // wxTreeItemId id = event.GetId();
1504 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1505 DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
1506 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1507 DeleteDicomDatabase(mItemOfMenu,r);
1509 //=====================================================================
1511 //=====================================================================
1512 void WxGimmick::OnPopUpDeleteCollection(wxCommandEvent& event)
1514 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;
1519 // std::cout << "OnPopUpClose"<<std::endl;
1520 // wxTreeItemId id = event.GetId();
1521 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1522 DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
1524 wxRemoveFile(std2wx(r->GetFileName()));
1525 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1526 DeleteDicomDatabase(mItemOfMenu,r);
1529 //=====================================================================
1531 void DisplayUpdateSummary( DicomDatabase::UpdateSummary& summary,
1534 std::stringstream mess;
1535 mess << "Dirs\tscanned\t\t\t: " << summary.scanned_dirs << "\n";
1536 mess << "Files\tscanned\t\t\t: " << summary.scanned_files << "\n";
1537 mess << "Files\thandled\t\t\t: " << summary.handled_images << "\n\n";
1538 mess << "Patients\tadded\t\t: " << summary.added_patients<< "\n";
1539 mess << "Studies\tadded\t\t: " << summary.added_studies<< "\n";
1540 mess << "Series\tadded\t\t: " << summary.added_series<< "\n";
1541 mess << "Images\tadded\t\t: " << summary.added_images<< "\n\n";
1543 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",
1545 (int)( summary.parse_time*100./summary.total_time),
1546 summary.file_scan_time,
1547 (int)(summary.file_scan_time*100./summary.total_time),
1548 summary.update_structs_time,
1549 (int)(summary.update_structs_time*100./summary.total_time),
1550 summary.update_database_time,
1551 (int)(summary.update_database_time*100./summary.total_time),
1552 summary.total_time );
1556 wxMessageBox(std2wx(mess.str()),_T("Update summary"),wxOK,parent);
1560 //=====================================================================
1561 void WxGimmick::OnPopUpAddFile(wxCommandEvent& event)
1563 long style = wxOPEN | wxFILE_MUST_EXIST | wxFD_MULTIPLE;
1564 std::string wc("*.*");
1565 wxFileDialog* FD = new wxFileDialog( 0,
1573 if (FD->ShowModal()==wxID_OK)
1577 mCurrentDirectory = FD->GetDirectory();
1578 wxArrayString files;
1579 FD->GetPaths(files);
1581 std::vector<std::string> filenames;
1582 for (i=0;i<files.GetCount();++i)
1583 filenames.push_back(wx2std(files[i]));
1586 TreeItemData *data =
1588 mTreeListCtrl->GetItemData(mItemOfMenu);
1589 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1590 DicomDatabase::UpdateSummary summary;
1591 wxProgressDialog* progress =
1592 new wxProgressDialog(_T("Adding file(s)"),
1597 wxPD_ESTIMATED_TIME |
1598 wxPD_REMAINING_TIME |
1601 db->AddFiles(filenames,progress,summary);
1603 progress->Pulse(_T("Updating view..."));
1604 UpdateDicomDatabaseView(db);
1606 DisplayUpdateSummary(summary,this);
1610 //=====================================================================
1612 //=====================================================================
1613 void WxGimmick::OnPopUpAddRawFile(wxCommandEvent& event)
1615 wxMessageBox(_T("Not yet implemented !"),_T("Sorry"),wxOK,this);
1617 //=====================================================================
1619 //=====================================================================
1620 void WxGimmick::OnPopUpAddDirectory(wxCommandEvent& event)
1622 long style = wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST;
1625 _T("Select directory"),
1629 if (FD->ShowModal()==wxID_OK)
1632 bool recurse = false;
1633 if (wxMessageBox(_T("Recurse into sub-directories ?"),
1634 _T("Scan directory"),
1635 wxYES_NO,this ) == wxYES)
1641 wxProgressDialog* progress =
1642 new wxProgressDialog(_T("Scanning directory"),
1643 _T("Parsing directory"),
1647 wxPD_ESTIMATED_TIME |
1648 wxPD_REMAINING_TIME |
1650 DicomDatabase::UpdateSummary summary;
1652 std::string dirname = wx2std (FD->GetPath()) ;
1653 mCurrentDirectory = FD->GetPath();
1654 TreeItemData *data =
1656 mTreeListCtrl->GetItemData(mItemOfMenu);
1657 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1658 db->AddDirectory(dirname,recurse,progress,summary);
1660 progress->Pulse(_T("Updating view..."));
1661 UpdateDicomDatabaseView(db);
1664 DisplayUpdateSummary(summary,this);
1666 if (summary.cancelled_by_user)
1668 std::cout << "!! Cancelled by user !!"<<std::endl;
1674 //=====================================================================
1676 //=====================================================================
1677 void WxGimmick::OnPopUpRemove(wxCommandEvent& event)
1681 wxMessageBox(_T("Not yet implemented"),_T("Sorry !"),wxOK);
1685 // wxTreeItemId id = event.GetId();
1686 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1688 std::string mess("Remove ");
1689 mess += data->GetDicomNode()->GetTypeName();
1690 mess += " from collection ?";
1691 int answer = wxMessageBox(std2wx(mess), _T("Confirm"), wxYES_NO);
1692 if (answer == wxNO) return;
1694 if ( mTreeListCtrl->IsSelected(mItemOfMenu) )
1696 wxTreeItemId next = mTreeListCtrl->GetNextSibling(mItemOfMenu);
1699 mTreeListCtrl->SelectItem(next);
1707 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1708 db->Remove(data->GetDicomNode());
1709 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1710 // TODO : Optimize update only parent's branch
1711 UpdateDicomDatabaseView(db);
1712 // DeleteDicomDatabase(mItemOfMenu,r);
1714 //=====================================================================
1716 //=====================================================================
1717 void WxGimmick::OnPopUpSort(wxCommandEvent& event)
1720 // std::cout << "OnPopUpSort"<<std::endl;
1721 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1722 int index = event.GetId() - PopUp_Sort;
1723 DicomNode* node = data->GetDicomNode();
1724 DicomNode::Type ctype = node->GetType()+1;
1725 mSettings.SetActiveComparatorIndex(ctype,index);
1727 if (node->ChildrenLoaded())
1730 mTreeListCtrl->DeleteChildren(mItemOfMenu);
1732 /* std::cout << "Sorting using '"
1733 << mSettings.GetActiveComparator(ctype).GetName()
1736 node->SortChildren ( mSettings.GetActiveComparator(ctype) );
1737 // std::cout << "ok"<<std::endl;
1741 CreateChildrenColumnsTitles(mItemOfMenu,ctype);
1742 DicomNode::ChildrenListType::iterator i;
1743 for (i=node->GetChildrenList().begin();
1744 i!=node->GetChildrenList().end();
1747 UpdateDicomNodeView(*i,mItemOfMenu);
1751 //=====================================================================
1754 //=====================================================================
1755 void WxGimmick::OnPopUpUser(wxCommandEvent& event)
1757 // std::cout << "OnPopUpUser"<<std::endl;
1760 //=====================================================================
1762 //=================================================
1763 void WxGimmick::CreateImageList(int size)
1767 mTreeListCtrl->SetImageList(NULL);
1776 // should correspond to Icon_xxx enum
1777 icons[Icon_Patient] = wxIcon(patient_xpm);
1778 icons[Icon_Study] = wxIcon(study_xpm);
1779 icons[Icon_Series] = wxIcon(series_xpm);
1780 icons[Icon_Image] = wxIcon(image_xpm);
1781 icons[Icon_Database] = wxIcon(database_xpm);
1782 icons[Icon_Folder] = wxIcon(folder_xpm);
1783 icons[Icon_DicomDir] = wxIcon(dicomdir_xpm);
1784 icons[Icon_Root] = wxIcon(root_xpm);
1787 // mFirstRootIconIndex = 8;
1790 Tree::RootHandlerListType::iterator h;
1792 for (h= Tree::GetDatabaseHandlerList().begin();
1793 h!=Tree::GetDatabaseHandlerList().end();
1796 icons[mFirstRootIconIndex+i] = (*h)->GetIcon();
1800 unsigned int NbIcons = 8;//mFirstRootIconIndex + i;
1801 // Make an image list containing small icons
1802 wxImageList *images = new wxImageList(size, size, true);
1804 int sizeOrig = icons[0].GetWidth();
1805 for ( size_t i = 0; i < NbIcons; i++ )
1807 if ( size == sizeOrig )
1809 images->Add(icons[i]);
1813 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
1816 mTreeListCtrl->AssignImageList(images);
1818 //=================================================
1827 //================================================================
1828 bool WxGimmick::IsImageSelectable(DicomNode* node)
1830 int rows = node->ImageGetRows();
1831 int cols = node->ImageGetColumns();
1832 int frms = node->ImageGetFrames();
1834 // std::cout << "R/C/F = " << rows << "/"<< cols <<"/"<<frms<<std::endl;
1838 else if (cols>0) dim=2;
1839 else if (rows>0) dim=1;
1843 std::cout << "Unknown image dimension : cannot select !"
1847 else if (dim>mSelectionMaxImageDimension)
1849 std::cout << "Selecting "<<dim<<"D images is not allowed !"
1854 if ( mTreeListCtrl->GetSelectionSize() == 0 )
1856 mCurrentSelectionImageSize[0] = cols;
1857 mCurrentSelectionImageSize[1] = rows;
1858 mCurrentSelectionImageSize[2] = frms;
1863 if ( dim == mSelectionMaxImageDimension )
1865 std::cout << "Cannot add this image to selection : would result in a "<<dim+1<<"D image !" << std::endl;
1868 if ( ( cols != mCurrentSelectionImageSize[0] ) ||
1869 ( rows != mCurrentSelectionImageSize[1] ) ||
1870 ( frms != mCurrentSelectionImageSize[2] ) )
1872 std::cout << "Cannot add this image to selection : image size is incomptatible with currently selected images" << std::endl;
1876 // std::cout << "Selecting : "<<node->ImageGetFullFileName() << std::endl;
1879 //================================================================
1881 //================================================================
1882 void WxGimmick::OnSelChanging(wxTreeEvent& event)
1885 wxTreeItemId id = event.GetItem();
1888 std::cout << "INTERNAL ERROR : ID NOT OK"<<std::endl;
1893 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1894 if (data->IsDicomNode())
1896 if (data->GetDicomNode()>0)
1898 // An image was selected
1899 if (data->GetDicomNode()->GetType()==DicomNode::Image)
1901 if (IsImageSelectable(data->GetDicomNode())) event.Allow();
1903 // A series was selected
1904 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
1906 // If images not loaded do it
1908 // can be selected if all its images can
1910 wxTreeItemIdValue cookie;
1911 for (child = mTreeListCtrl->GetFirstChild(id,cookie);
1913 child = mTreeListCtrl->GetNextChild(id,cookie))
1915 TreeItemData *cdata =
1916 (TreeItemData *)mTreeListCtrl->GetItemData(child);
1917 if ((cdata->IsDicomNode())&&
1918 (cdata->GetDicomNode()>0)&&
1919 (cdata->GetDicomNode()->GetType()==DicomNode::Image)&&
1920 (!IsImageSelectable(cdata->GetDicomNode())))
1928 //================================================================
1930 //================================================================
1931 void WxGimmick::OnSelChanged(wxTreeEvent& event)
1933 // wxBusyCursor busy;
1934 // std::vector<wxTreeItemId> items;
1935 // GetSelectedItems(items);
1937 std::vector<DicomNode*>::iterator i;
1938 for (i=nodes.begin();i!=nodes.end();++i)
1940 std::cout << "'" << (*i)->GetFieldValue("FullFileName")
1941 << "'" << std::endl;
1943 std::cout << "++++++++++++++++++++" << std::endl;
1945 // ShowImage(mReader.GetImage(""));
1947 bool no_image = true;
1949 static int max = 1000;
1952 // if (items.size()>0)
1955 // Update image preview : send requests to the MTImageReader
1956 // bool first = true;
1957 // std::vector<wxTreeItemId>::iterator i;
1958 // for (i=items.begin();i!=items.end();++i)
1964 DicomNode* node = GetDicomNodeOfItem(items[0]);
1966 // Update dicom fields panel
1967 mFieldsView->UpdateValues(node);
1971 wxTreeItemId item = mTreeListCtrl->GetCurrent();
1973 DicomNode* n = GetDicomNodeOfItem(item);
1975 if (n) mFieldsView->UpdateValues(n);
1978 (n->GetType()==DicomNode::Image) )
1983 //if (i==items.begin())
1984 mCurImageItemToShow = item;
1986 int maxprio = mReader.GetMaximalPriority();
1987 int prio = maxprio + 1000;
1988 wxTreeItemId sib = item; //GetTreeListCtrl()->GetNextSibling(*i);
1991 DicomNode* nsib = GetDicomNodeOfItem(sib);
1994 // std::cout << "-- Request '"
1995 // << nsib->GetFieldValue("FullFileName")
1996 // << "' prio="<<prio<<std::endl;
1997 mReader.Request(this,
1998 nsib->ImageGetFullFileName(),
2000 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
2004 sib = GetTreeListCtrl()->GetNextSibling(sib);
2006 prio = maxprio + 999;
2007 sib = GetTreeListCtrl()->GetPrevSibling(item);
2010 DicomNode* nsib = GetDicomNodeOfItem(sib);
2013 // std::cout << "-- Request '"
2014 // << nsib->GetFieldValue("FullFileName")
2015 // << "' prio="<<prio<<std::endl;
2016 mReader.Request(this,
2017 nsib->ImageGetFullFileName(),
2019 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
2023 sib = GetTreeListCtrl()->GetPrevSibling(sib);
2025 // mImageFileNameToNode[n->GetFieldValue("FullFileName")] = n;
2028 ProcessImageEvents();
2030 // std::cout << "* Selection changed * (im)"<<std::endl;
2032 //---------------------------------------------------------------------
2034 WxGimmickEvent ev(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED,
2038 GetEventHandler()->ProcessEvent(ev);
2040 if (no_image) ShowImage(mReader.GetImage(""));
2043 //================================================================
2045 //================================================================
2046 void WxGimmick::ShowImage(vtkImageData* im)
2048 // wxBusyCursor busy;
2049 mViewer->SetInput( im );
2050 mViewer->SetSlice( 0 );
2053 int x1,x2,y1,y2,z1,z2;
2056 im->GetSpacing(spx,spy,spz);
2057 im->GetExtent (x1,x2,y1,y2,z1,z2);
2059 std::cout << "-----------------------------"<<std::endl;
2060 std::cout << x1 << "-"<<x2<<std::endl;
2061 std::cout << y1 << "-"<<y2<<std::endl;
2062 std::cout << z1 << "-"<<z2<<std::endl;
2063 std::cout << spx << "-"<<spy<<"-"<<spz<<std::endl;
2087 double *range = im->GetScalarRange();
2088 mViewer->SetColorWindow(range[1] - range[0]);
2089 mViewer->SetColorLevel(0.5 * (range[1] + range[0]));
2091 mViewer->GetRenderer()->ResetCamera();
2095 mViewer->GetRenderer()->ComputeVisiblePropBounds(bounds);
2098 std::cout <<"bounds : "<<bounds[0]<<","
2103 <<bounds[5]<<std::endl;
2105 mViewer->GetRenderer()->ResetCameraClippingRange(bounds);
2107 vtkCamera *camera = mViewer->GetRenderer()->GetActiveCamera();
2109 camera->SetViewUp ( spx*0, -spy*1, spz*0);
2110 camera->SetPosition( spx*(x1+x2)/2, spy*(y1+y2)/2, spz*10000000);
2111 camera->SetFocalPoint ( spx*(x1+x2)/2 , spy*(y1+y2)/2 , spz*0);
2113 camera->ComputeViewPlaneNormal();
2114 camera->SetParallelScale( spx*(x2-x1)/2.0 );
2116 camera->Roll ( 180 );
2120 mInteractor->Render();
2122 //================================================================
2129 //================================================================
2131 OnMultiThreadImageReaderEvent(const std::string& filename,
2132 MultiThreadImageReaderUser::EventType e,
2133 vtkImageData* image)
2135 if (filename.size()==0)
2137 mImageEventQueue.push_back(ImageEventType(image));
2140 std::map<std::string,DicomNode*>::iterator i;
2141 i = mImageFileNameToNode.find(filename);
2142 if (i!=mImageFileNameToNode.end())
2144 wxTreeItemId id = i->second->GetData<NodeData*>()->GetTreeItemData()->GetItemId();
2145 mImageEventQueue.push_back(ImageEventType(id,image));
2148 //================================================================
2150 //================================================================
2151 // Processes the queue of image events
2152 void WxGimmick::ProcessImageEvents()
2154 // std::cout << "++++++++++ ProcessImageEvents " << std::endl;
2155 MultiThreadImageReaderEventLock();
2158 while (!mImageEventQueue.empty())
2160 ImageEventType e = mImageEventQueue.front();
2161 mImageEventQueue.pop_front();
2166 mTreeListCtrl->SetItemTextColour(e.item,
2167 mSettings.LoadedImageColour());//wxImageLoadedColour);
2168 TreeItemData *data =
2169 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2170 data->SetLoaded(true);
2172 if (mCurImageItemToShow == e.item)
2177 else if (!mCurImageItemToShow.IsOk())
2182 else if (e.item.IsOk())
2184 mTreeListCtrl->SetItemTextColour(e.item,mSettings.Colour(DicomNode::Image)); //.wxImageUnloadedColour);
2185 TreeItemData *data =
2186 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2187 data->SetLoaded(false);
2190 mImageEventQueue.clear();
2191 MultiThreadImageReaderEventUnlock();
2192 // std::cout << "++++++++++ END ProcessImageEvents " << std::endl;
2194 //================================================================
2196 //================================================================
2197 void WxGimmick::OnInternalIdle()
2199 ProcessImageEvents();
2204 mJustStarted = false;
2209 //================================================================
2212 //================================================================
2213 // LG : For the moment any selection is valid but in the future
2214 // incomplete selections can be invalid...
2215 bool WxGimmick::IsSelectionValid()
2217 return (mTreeListCtrl->GetSelectionSize()>0);
2219 //================================================================
2221 //================================================================
2222 void WxGimmick::GetSelectedFiles(std::vector<std::string>& f)
2224 wxArrayTreeItemIds id;
2225 // TO DO : TEST THAT STYLE IS MULTIPLE
2226 unsigned int nb = mTreeListCtrl->GetSelections(id);
2228 for (unsigned int i=0; i<nb; ++i)
2230 TreeItemData *data =
2231 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2232 if ((data) && (data->IsDicomNode()))
2234 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2236 f.push_back ( data->GetDicomNode()->ImageGetFullFileName() );
2238 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2240 DicomNode::ChildrenListType::iterator j;
2241 for (j =data->GetDicomNode()->GetChildrenList().begin();
2242 j!=data->GetDicomNode()->GetChildrenList().end();
2245 f.push_back((*j)->ImageGetFullFileName());
2251 //================================================================
2253 //================================================================
2254 void WxGimmick::GetSelectedImages(std::vector<vtkImageData*>& f)
2256 wxArrayTreeItemIds id;
2257 // TO DO : TEST THAT STYLE IS MULTIPLE
2258 unsigned int nb = mTreeListCtrl->GetSelections(id);
2261 // Collect the brute vector of Image nodes
2262 std::vector<DicomNode*> im;
2263 for (unsigned int i=0; i<nb; ++i)
2265 TreeItemData *data =
2266 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2267 if ((data) && (data->IsDicomNode()))
2269 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2271 im.push_back ( data->GetDicomNode() );
2274 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2276 DicomNode::ChildrenListType::iterator j;
2277 for (j =data->GetDicomNode()->GetChildrenList().begin();
2278 j!=data->GetDicomNode()->GetChildrenList().end();
2281 im.push_back ( *j );
2286 // Create the output data
2289 // Only one image : give it
2290 vtkImageData* out = vtkImageData::New();
2291 out->ShallowCopy(mReader.GetImage(im.front()->ImageGetFullFileName()));
2294 else if (im.size()>1)
2296 vtkImageData* first = mReader.GetImage( im.front()->ImageGetFullFileName() );
2297 if (first->GetDataDimension()==2)
2300 vtkImageData* out = vtkImageData::New();
2301 out->CopyStructure(first);
2302 out->SetScalarType(first->GetScalarType());
2304 first->GetExtent(ext);
2306 out->SetExtent(ext);
2307 // LG : TODO : Z Spacing ?
2309 // ==> to get an accurate ZSpacing from a Dicom set of files
2310 // ==> you need a gdcm::SerieHelper
2313 out->AllocateScalars();
2315 //first->Print(std::cout);
2316 // out->Print(std::cout);
2319 first->GetDimensions(dim);
2320 unsigned long imsize =
2321 ( (unsigned long)first->GetScalarPointer(0,1,0)
2322 - (unsigned long)first->GetScalarPointer(0,0,0))
2326 std::vector<DicomNode*>::iterator it;
2327 for (it=im.begin(); it!=im.end(); ++it)
2329 //std::cout << "copying slice "<<slice <<std::endl;
2330 vtkImageData* cur = mReader.GetImage( (*it)->ImageGetFullFileName() );
2332 void* src = cur->GetScalarPointer(0,0,0);
2333 void* dst = out->GetScalarPointer(0,0,slice);
2334 // std::cout << "src="<<src<<std::endl;
2335 // std::cout << "dst="<<dst<<std::endl;
2336 // std::cout << "siz="<<imsize<<std::endl;
2337 memcpy(dst,src,imsize);
2342 for (ii=1;ii<4;ii++) {
2343 for (jj=1;jj<4;jj++) {
2344 int x = (int)(ii*dim[0] / 4);
2345 int y = (int)(jj*dim[1] / 4);
2346 std::cout << cur->GetScalarComponentAsFloat(x,y,0,0)
2348 << out->GetScalarComponentAsFloat(x,y,slice,0)
2361 std::vector<DicomNode*>::iterator it;
2362 for (it=im.begin(); it!=im.end(); ++it)
2364 vtkImageData* out = vtkImageData::New();
2365 out->ShallowCopy(mReader.GetImage((*it)->ImageGetFullFileName()));
2371 //================================================================
2374 //================================================================
2375 void WxGimmick::GetSelectedDicomNodes(std::vector<DicomNode*>& f)
2377 wxArrayTreeItemIds id;
2378 // TO DO : TEST THAT STYLE IS MULTIPLE
2379 unsigned int nb = mTreeListCtrl->GetSelections(id);
2381 for (unsigned int i=0; i<nb; ++i)
2383 TreeItemData *data =
2384 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2385 if ((data) && (data->IsDicomNode()))
2387 f.push_back ( data->GetDicomNode() );
2391 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2393 f.push_back ( data->GetDicomNode() ); //->ImageGetFullFileName() );
2395 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2397 DicomNode::ChildrenListType::iterator j;
2398 for (j =data->GetDicomNode()->GetChildrenList().begin();
2399 j!=data->GetDicomNode()->GetChildrenList().end();
2402 f.push_back((*j)); //->ImageGetFullFileName() ); }
2408 //================================================================
2410 //================================================================
2411 void WxGimmick::GetSelectedItems(std::vector<wxTreeItemId>& f)
2413 wxArrayTreeItemIds id;
2414 // TO DO : TEST THAT STYLE IS MULTIPLE
2415 unsigned int nb = mTreeListCtrl->GetSelections(id);
2417 for (unsigned int i=0; i<nb; ++i)
2422 //================================================================
2424 //================================================================
2425 DicomNode* WxGimmick::GetDicomNodeOfItem(const wxTreeItemId& i)
2427 TreeItemData *data =
2428 (TreeItemData *)mTreeListCtrl->GetItemData(i);
2429 if (data) return ( data->GetDicomNode() );
2432 //================================================================
2434 //================================================================
2435 //================================================================
2436 //================================================================
2437 //================================================================
2453 //================================================================
2454 //================================================================
2455 //================================================================
2456 //================================================================
2458 BEGIN_EVENT_TABLE(WxGimmick, wxPanel)
2460 EVT_MENU(PopUp_NewCollection,WxGimmick::OnPopUpNewCollection)
2461 EVT_MENU(PopUp_OpenCollection,WxGimmick::OnPopUpOpenCollection)
2462 EVT_MENU(PopUp_CloseCollection,WxGimmick::OnPopUpCloseCollection)
2463 EVT_MENU(PopUp_DeleteCollection,WxGimmick::OnPopUpDeleteCollection)
2464 EVT_MENU(PopUp_AddFile, WxGimmick::OnPopUpAddFile)
2465 EVT_MENU(PopUp_AddRawFile, WxGimmick::OnPopUpAddRawFile)
2466 EVT_MENU(PopUp_AddDirectory, WxGimmick::OnPopUpAddDirectory)
2467 EVT_MENU(PopUp_Remove, WxGimmick::OnPopUpRemove)
2468 EVT_MENU(PopUp_About, WxGimmick::OnPopUpAbout)
2469 EVT_MENU(PopUp_Settings, WxGimmick::OnPopUpSettings)
2471 EVT_MENU_RANGE(PopUp_Sort, PopUp_Sort+99, WxGimmick::OnPopUpSort)
2472 EVT_MENU_RANGE(PopUp_User, PopUp_User+99, WxGimmick::OnPopUpUser)
2477 EVT_TREE_BEGIN_DRAG(TreeListCtrlId, WxGimmick::OnBeginDrag)
2478 EVT_TREE_BEGIN_RDRAG(TreeListCtrlId, WxGimmick::OnBeginRDrag)
2479 EVT_TREE_END_DRAG(TreeListCtrlId, WxGimmick::OnEndDrag)
2482 EVT_TREE_BEGIN_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnBeginLabelEdit)
2483 EVT_TREE_END_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnEndLabelEdit)
2486 EVT_TREE_DELETE_ITEM(TreeListCtrlId, WxGimmick::OnDeleteItem)
2487 #if 0 // there are so many of those that logging them causes flicker
2488 EVT_TREE_GET_INFO(TreeListCtrlId, WxGimmick::OnGetInfo)
2491 EVT_TREE_SET_INFO(TreeListCtrlId, WxGimmick::OnSetInfo)
2494 EVT_TREE_ITEM_EXPANDED(TreeListCtrlId, WxGimmick::OnItemExpanded)
2495 EVT_TREE_ITEM_EXPANDING(TreeListCtrlId, WxGimmick::OnItemExpanding)
2496 EVT_TREE_ITEM_COLLAPSED(TreeListCtrlId, WxGimmick::OnItemCollapsed)
2497 EVT_TREE_ITEM_COLLAPSING(TreeListCtrlId, WxGimmick::OnItemCollapsing)
2500 EVT_TREE_SEL_CHANGED(TreeListCtrlId, WxGimmick::OnSelChanged)
2501 EVT_TREE_SEL_CHANGING(TreeListCtrlId, WxGimmick::OnSelChanging)
2503 EVT_TREE_KEY_DOWN(TreeListCtrlId, WxGimmick::OnTreeKeyDown)
2504 // ACTIVATION = DOUBLE CLICK OR ENTER ON SELECTED
2505 EVT_TREE_ITEM_ACTIVATED(TreeListCtrlId, WxGimmick::OnItemActivated)
2507 // so many differents ways to handle right mouse button clicks...
2508 // EVT_CONTEXT_MENU(WxGimmick::OnContextMenu)
2509 // EVT_TREE_ITEM_MENU is the preferred event for creating context menus
2510 // on a tree control, because it includes the point of the click or item,
2511 // meaning that no additional placement calculations are required.
2512 // EVT_TREE_ITEM_MENU(TreeListCtrlId, WxGimmick::OnItemMenu)
2514 EVT_TREE_ITEM_RIGHT_CLICK(TreeListCtrlId, WxGimmick::OnItemRightClick)
2517 // EVT_RIGHT_DOWN(WxGimmick::OnRMouseDown)
2518 // EVT_RIGHT_UP(WxGimmick::OnRMouseUp)
2519 // EVT_RIGHT_DCLICK(WxGimmick::OnRMouseDClick)
2522 //IMPLEMENT_DYNAMIC_CLASS(WxGimmick, wxTreeListCtrl)
2525 wxTree::wxTree(wxWindow *parent, const wxWindowID id,
2526 const wxPoint& pos, const wxSize& size,
2528 : wxTreeListCtrl(parent, id, pos, size, style)
2530 m_reverseSort = false;
2534 // Add some items to the tree
2535 AddTestItemsToTree(5, 2);
2541 #if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
2542 void WxGimmick::CreateButtonsImageList(int size)
2547 mTreeListCtrl->SetButtonsImageList(NULL);
2551 // Make an image list containing small icons
2552 wxImageList *images = new wxImageList(size, size, true);
2554 // should correspond to TreeListCtrlIcon_xxx enum
2557 icons[0] = wxIcon(icon3_xpm); // closed
2558 icons[1] = wxIcon(icon3_xpm); // closed, selected
2559 icons[2] = wxIcon(icon5_xpm); // open
2560 icons[3] = wxIcon(icon5_xpm); // open, selected
2562 for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
2564 int sizeOrig = icons[i].GetWidth();
2565 if ( size == sizeOrig )
2567 images->Add(icons[i]);
2571 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
2575 mTreeListCtrl->AssignButtonsImageList(images);
2578 void WxGimmick::CreateButtonsImageList(int WXUNUSED(size))
2584 int WxGimmick::OnCompareItems(const wxTreeItemId& item1,
2585 const wxTreeItemId& item2)
2587 if ( m_reverseSort )
2589 // just exchange 1st and 2nd items
2590 return mTreeListCtrl->OnCompareItems(item2, item1);
2594 return mTreeListCtrl->OnCompareItems(item1, item2);
2599 void WxGimmick::DoToggleIcon(const wxTreeItemId& item)
2602 int image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_Folder)
2605 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Normal);
2607 image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_FolderSelected)
2608 ? TreeIcon_FileSelected
2609 : TreeIcon_FolderSelected;
2610 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Selected);
2613 void WxGimmick::LogEvent(const wxChar *name, const wxTreeEvent& event)
2615 wxTreeItemId item = event.GetItem();
2618 text << _T('"') << mTreeListCtrl->GetItemText(item).c_str() << _T('"');
2620 text = _T("invalid item");
2621 // wxLogMessage(wxT("%s(%s)"), name, text.c_str());
2626 #define TREE_EVENT_HANDLER(name) \
2627 void WxGimmick::name(wxTreeEvent& event) \
2629 /* LogEvent(_T(#name), event); */ \
2630 /* SetLastItem(mTreeListCtrl->wxTreeItemId()) *;*/ \
2634 TREE_EVENT_HANDLER(OnBeginRDrag)
2635 TREE_EVENT_HANDLER(OnDeleteItem)
2636 TREE_EVENT_HANDLER(OnGetInfo)
2637 TREE_EVENT_HANDLER(OnSetInfo)
2638 //TREE_EVENT_HANDLER(OnItemExpanded)
2639 TREE_EVENT_HANDLER(OnItemExpanding)
2640 //TREE_EVENT_HANDLER(OnItemCollapsed)
2641 //TREE_EVENT_HANDLER(OnSelChanged)
2642 // TREE_EVENT_HANDLER(OnSelChanging)
2645 void WxGimmick::OnItemCollapsed(wxTreeEvent& event)
2647 // std::cout << "* Collapsed *"<<std::endl;
2650 #undef TREE_EVENT_HANDLER
2652 void WxGimmick::OnTreeKeyDown(wxTreeEvent& event)
2655 // LogKeyEvent(wxT("Tree key down "), event.GetKeyEvent());
2656 std::cout << "* Key down *"<<std::endl;
2657 if (event.GetKeyCode()==WXK_RIGHT)
2659 std::cout << "Right"<<std::endl;
2660 wxTreeItemId itemId = mTreeListCtrl->GetSelection();
2663 std::cout << "item is ok"<<std::endl;
2664 wxPoint clientpt = event.GetPoint();
2665 wxPoint screenpt = ClientToScreen(clientpt);
2666 ShowMenu(itemId, clientpt);
2671 std::cout << "NOT Right"<<std::endl;
2676 void WxGimmick::OnBeginDrag(wxTreeEvent& event)
2678 wxTreeItemId id = event.GetItem();
2679 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2680 // std::cout << "OnBeginDrag("<<id<<")"<<std::endl;
2681 if (data->IsDatabase())
2683 // std::cout << "-- IS ROOT"<<std::endl;
2686 else if (data->IsDicomNode())
2688 // std::cout << "-- IS NODE"<<std::endl;
2691 // need to explicitly allow drag
2692 if ( event.GetItem() != GetDatabaseItem() )
2694 m_draggedItem = event.GetItem();
2696 wxPoint clientpt = event.GetPoint();
2697 wxPoint screenpt = ClientToScreen(clientpt);
2699 wxLogMessage(wxT("OnBeginDrag: started dragging %s at screen coords (%i,%i)"),
2700 GetItemText(m_draggedItem).c_str(),
2701 screenpt.x, screenpt.y);
2707 wxLogMessage(wxT("OnBeginDrag: this item can't be dragged."));
2712 void WxGimmick::OnEndDrag(wxTreeEvent& event)
2714 wxTreeItemId id = event.GetItem();
2715 // std::cout << "OnEndDrag("<<id<<")"<<std::endl;
2716 if (!id.IsOk()) return;
2717 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2718 if (data->IsDatabase())
2720 // std::cout << "-- IS ROOT"<<std::endl;
2722 else if (data->IsDicomNode())
2724 // std::cout << "-- IS NODE"<<std::endl;
2728 wxTreeItemId itemSrc = m_draggedItem,
2729 itemDst = event.GetItem();
2730 m_draggedItem = (wxTreeItemId)0l;
2732 // where to copy the item?
2733 if ( itemDst.IsOk() && !ItemHasChildren(itemDst) )
2735 // copy to the parent then
2736 itemDst = GetItemParent(itemDst);
2739 if ( !itemDst.IsOk() )
2741 wxLogMessage(wxT("OnEndDrag: can't drop here."));
2746 wxString text = GetItemText(itemSrc);
2747 wxLogMessage(wxT("OnEndDrag: '%s' copied to '%s'."),
2748 text.c_str(), GetItemText(itemDst).c_str());
2750 // just do append here - we could also insert it just before/after the item
2751 // on which it was dropped, but this requires slightly more work... we also
2752 // completely ignore the client data and icon of the old item but could
2753 // copy them as well.
2755 // Finally, we only copy one item here but we might copy the entire tree if
2756 // we were dragging a folder.
2757 int image = wxGetApp().ShowImages() ? TreeIcon_File : -1;
2758 AppendItem(itemDst, text, image);
2763 //====================================================================
2764 void WxGimmick::OnBeginLabelEdit(wxTreeEvent& event)
2766 // std::cout << "OnBeginLabelEdit"<<std::endl;
2767 wxTreeItemId id = event.GetItem();
2768 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2769 // If not a root : veto
2770 if (data->IsDatabase())
2777 //====================================================================
2779 //====================================================================
2780 void WxGimmick::OnEndLabelEdit(wxTreeEvent& event)
2782 // std::cout << "OnEndLabelEdit"<<std::endl;
2783 wxTreeItemId id = event.GetItem();
2784 TreeItemData *data = GetItemData(id);
2785 // If not a database : bug !
2786 if (data->IsDatabase())
2788 data->GetDicomNode()->GetDicomDatabase()->SetName(wx2std(event.GetLabel()));
2789 mFieldsView->UpdateValues(data->GetDicomNode());
2793 std::cerr<< "!!!! Internal error : send bug report !!!!"<<std::endl;
2796 //====================================================================
2799 void WxGimmick::OnItemCollapsing(wxTreeEvent& event)
2801 // wxLogMessage(wxT("OnItemCollapsing"));
2803 // for testing, prevent the user from collapsing the first child folder
2804 wxTreeItemId itemId = event.GetItem();
2807 if ( IsTestItem(itemId) )
2809 wxMessageBox(wxT("You can't collapse this item."));
2817 //====================================================================
2818 void WxGimmick::ShowHelp()
2823 mHelpWindow = new WxGimmickHelpWindow(this);
2825 mHelpWindow->CenterOnParent();
2826 mHelpWindow->ShowModal();
2829 //====================================================================
2835 //================================================================
2836 //================================================================
2837 //================================================================
2838 //================================================================
2839 //================================================================
2841 //================================================================
2842 //================================================================
2843 //================================================================
2844 //================================================================
2845 //================================================================
2851 // ----------------------------------------------------------------------------
2853 // ----------------------------------------------------------------------------
2855 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_DRAG)
2856 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_RDRAG)
2857 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_DELETE_ITEM)
2858 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_GET_INFO)
2859 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SET_INFO)
2860 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDED)
2861 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDING)
2862 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSED)
2863 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSING)
2866 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT)
2867 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_LABEL_EDIT)
2870 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED)
2871 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGING)
2872 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_KEY_DOWN)
2873 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU)
2874 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_ITEM_STYLE_CHANGED)
2876 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_ACTIVATED)
2877 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK)
2878 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK)
2879 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_DRAG)
2880 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK)
2881 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP)
2882 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MENU)
2884 // ----------------------------------------------------------------------------
2886 // ----------------------------------------------------------------------------
2888 IMPLEMENT_ABSTRACT_CLASS(WxGimmickEvent, wxNotifyEvent)
2891 WxGimmickEvent::WxGimmickEvent(wxEventType commandType,
2893 const wxTreeItemId& item)
2895 wxNotifyEvent(commandType, tree->GetId()),
2899 // m_editCancelled = false;
2901 SetEventObject(tree);
2904 SetClientObject(tree->mTreeListCtrl->GetItemData(item));
2907 WxGimmickEvent::WxGimmickEvent(wxEventType commandType, int id)
2909 wxNotifyEvent(commandType, id),
2913 // m_editCancelled = false;
2916 WxGimmickEvent::WxGimmickEvent(const WxGimmickEvent & event)
2918 wxNotifyEvent(event),
2922 m_evtKey = event.m_evtKey;
2923 m_item = event.m_item;
2924 m_itemOld = event.m_itemOld;
2925 mColor = event.mColor;
2926 mUserData = event.mUserData;
2927 // m_pointDrag = event.m_pointDrag;
2928 // m_label = event.m_label;
2929 // m_editCancelled = event.m_editCancelled;
2939 //================================================================
2940 //================================================================
2941 //================================================================
2942 //================================================================
2943 //================================================================
2944 WxGimmickFrame::WxGimmickFrame( wxWindow *parent,
2947 : wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size)
2949 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
2950 mWxGimmick = new WxGimmick(this,-1,
2953 sizer->Add(mWxGimmick,1,wxGROW);
2955 SetAutoLayout(true);
2958 //================================================================
2960 //================================================================
2961 WxGimmickFrame::~WxGimmickFrame()
2964 //================================================================
2966 //================================================================
2967 void WxGimmickFrame::OnSelChanged(WxGimmickEvent& event)
2969 // std::cout << "+++++ WxGimmickFrame::OnSelChanged ++++++++++"
2971 std::vector<std::string> file;
2972 // mWxGimmick->GetSelectedImages(file);
2974 std::vector<std::string>::iterator i;
2975 for (i=file.begin();i!=file.end();++i)
2977 std::cout << "'" << *i << "'" << std::endl;
2979 std::cout << "++++++++++++++++++++" << std::endl;
2982 //================================================================
2984 //================================================================
2985 BEGIN_EVENT_TABLE(WxGimmickFrame, wxFrame)
2986 EVT_TREEVIEWLIST_SEL_CHANGED(-1,WxGimmickFrame::OnSelChanged)
2988 //================================================================