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 out->AllocateScalars();
2311 //first->Print(std::cout);
2312 // out->Print(std::cout);
2315 first->GetDimensions(dim);
2316 unsigned long imsize =
2317 ( (unsigned long)first->GetScalarPointer(0,1,0)
2318 - (unsigned long)first->GetScalarPointer(0,0,0))
2322 std::vector<DicomNode*>::iterator it;
2323 for (it=im.begin(); it!=im.end(); ++it)
2325 //std::cout << "copying slice "<<slice <<std::endl;
2326 vtkImageData* cur = mReader.GetImage( (*it)->ImageGetFullFileName() );
2328 void* src = cur->GetScalarPointer(0,0,0);
2329 void* dst = out->GetScalarPointer(0,0,slice);
2330 // std::cout << "src="<<src<<std::endl;
2331 // std::cout << "dst="<<dst<<std::endl;
2332 // std::cout << "siz="<<imsize<<std::endl;
2333 memcpy(dst,src,imsize);
2338 for (ii=1;ii<4;ii++) {
2339 for (jj=1;jj<4;jj++) {
2340 int x = (int)(ii*dim[0] / 4);
2341 int y = (int)(jj*dim[1] / 4);
2342 std::cout << cur->GetScalarComponentAsFloat(x,y,0,0)
2344 << out->GetScalarComponentAsFloat(x,y,slice,0)
2357 std::vector<DicomNode*>::iterator it;
2358 for (it=im.begin(); it!=im.end(); ++it)
2360 vtkImageData* out = vtkImageData::New();
2361 out->ShallowCopy(mReader.GetImage((*it)->ImageGetFullFileName()));
2367 //================================================================
2370 //================================================================
2371 void WxGimmick::GetSelectedDicomNodes(std::vector<DicomNode*>& f)
2373 wxArrayTreeItemIds id;
2374 // TO DO : TEST THAT STYLE IS MULTIPLE
2375 unsigned int nb = mTreeListCtrl->GetSelections(id);
2377 for (unsigned int i=0; i<nb; ++i)
2379 TreeItemData *data =
2380 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2381 if ((data) && (data->IsDicomNode()))
2383 f.push_back ( data->GetDicomNode() );
2387 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2389 f.push_back ( data->GetDicomNode() ); //->ImageGetFullFileName() );
2391 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2393 DicomNode::ChildrenListType::iterator j;
2394 for (j =data->GetDicomNode()->GetChildrenList().begin();
2395 j!=data->GetDicomNode()->GetChildrenList().end();
2398 f.push_back((*j)); //->ImageGetFullFileName() ); }
2404 //================================================================
2406 //================================================================
2407 void WxGimmick::GetSelectedItems(std::vector<wxTreeItemId>& f)
2409 wxArrayTreeItemIds id;
2410 // TO DO : TEST THAT STYLE IS MULTIPLE
2411 unsigned int nb = mTreeListCtrl->GetSelections(id);
2413 for (unsigned int i=0; i<nb; ++i)
2418 //================================================================
2420 //================================================================
2421 DicomNode* WxGimmick::GetDicomNodeOfItem(const wxTreeItemId& i)
2423 TreeItemData *data =
2424 (TreeItemData *)mTreeListCtrl->GetItemData(i);
2425 if (data) return ( data->GetDicomNode() );
2428 //================================================================
2430 //================================================================
2431 //================================================================
2432 //================================================================
2433 //================================================================
2449 //================================================================
2450 //================================================================
2451 //================================================================
2452 //================================================================
2454 BEGIN_EVENT_TABLE(WxGimmick, wxPanel)
2456 EVT_MENU(PopUp_NewCollection,WxGimmick::OnPopUpNewCollection)
2457 EVT_MENU(PopUp_OpenCollection,WxGimmick::OnPopUpOpenCollection)
2458 EVT_MENU(PopUp_CloseCollection,WxGimmick::OnPopUpCloseCollection)
2459 EVT_MENU(PopUp_DeleteCollection,WxGimmick::OnPopUpDeleteCollection)
2460 EVT_MENU(PopUp_AddFile, WxGimmick::OnPopUpAddFile)
2461 EVT_MENU(PopUp_AddRawFile, WxGimmick::OnPopUpAddRawFile)
2462 EVT_MENU(PopUp_AddDirectory, WxGimmick::OnPopUpAddDirectory)
2463 EVT_MENU(PopUp_Remove, WxGimmick::OnPopUpRemove)
2464 EVT_MENU(PopUp_About, WxGimmick::OnPopUpAbout)
2465 EVT_MENU(PopUp_Settings, WxGimmick::OnPopUpSettings)
2467 EVT_MENU_RANGE(PopUp_Sort, PopUp_Sort+99, WxGimmick::OnPopUpSort)
2468 EVT_MENU_RANGE(PopUp_User, PopUp_User+99, WxGimmick::OnPopUpUser)
2473 EVT_TREE_BEGIN_DRAG(TreeListCtrlId, WxGimmick::OnBeginDrag)
2474 EVT_TREE_BEGIN_RDRAG(TreeListCtrlId, WxGimmick::OnBeginRDrag)
2475 EVT_TREE_END_DRAG(TreeListCtrlId, WxGimmick::OnEndDrag)
2478 EVT_TREE_BEGIN_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnBeginLabelEdit)
2479 EVT_TREE_END_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnEndLabelEdit)
2482 EVT_TREE_DELETE_ITEM(TreeListCtrlId, WxGimmick::OnDeleteItem)
2483 #if 0 // there are so many of those that logging them causes flicker
2484 EVT_TREE_GET_INFO(TreeListCtrlId, WxGimmick::OnGetInfo)
2487 EVT_TREE_SET_INFO(TreeListCtrlId, WxGimmick::OnSetInfo)
2490 EVT_TREE_ITEM_EXPANDED(TreeListCtrlId, WxGimmick::OnItemExpanded)
2491 EVT_TREE_ITEM_EXPANDING(TreeListCtrlId, WxGimmick::OnItemExpanding)
2492 EVT_TREE_ITEM_COLLAPSED(TreeListCtrlId, WxGimmick::OnItemCollapsed)
2493 EVT_TREE_ITEM_COLLAPSING(TreeListCtrlId, WxGimmick::OnItemCollapsing)
2496 EVT_TREE_SEL_CHANGED(TreeListCtrlId, WxGimmick::OnSelChanged)
2497 EVT_TREE_SEL_CHANGING(TreeListCtrlId, WxGimmick::OnSelChanging)
2499 EVT_TREE_KEY_DOWN(TreeListCtrlId, WxGimmick::OnTreeKeyDown)
2500 // ACTIVATION = DOUBLE CLICK OR ENTER ON SELECTED
2501 EVT_TREE_ITEM_ACTIVATED(TreeListCtrlId, WxGimmick::OnItemActivated)
2503 // so many differents ways to handle right mouse button clicks...
2504 // EVT_CONTEXT_MENU(WxGimmick::OnContextMenu)
2505 // EVT_TREE_ITEM_MENU is the preferred event for creating context menus
2506 // on a tree control, because it includes the point of the click or item,
2507 // meaning that no additional placement calculations are required.
2508 // EVT_TREE_ITEM_MENU(TreeListCtrlId, WxGimmick::OnItemMenu)
2510 EVT_TREE_ITEM_RIGHT_CLICK(TreeListCtrlId, WxGimmick::OnItemRightClick)
2513 // EVT_RIGHT_DOWN(WxGimmick::OnRMouseDown)
2514 // EVT_RIGHT_UP(WxGimmick::OnRMouseUp)
2515 // EVT_RIGHT_DCLICK(WxGimmick::OnRMouseDClick)
2518 //IMPLEMENT_DYNAMIC_CLASS(WxGimmick, wxTreeListCtrl)
2521 wxTree::wxTree(wxWindow *parent, const wxWindowID id,
2522 const wxPoint& pos, const wxSize& size,
2524 : wxTreeListCtrl(parent, id, pos, size, style)
2526 m_reverseSort = false;
2530 // Add some items to the tree
2531 AddTestItemsToTree(5, 2);
2537 #if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
2538 void WxGimmick::CreateButtonsImageList(int size)
2543 mTreeListCtrl->SetButtonsImageList(NULL);
2547 // Make an image list containing small icons
2548 wxImageList *images = new wxImageList(size, size, true);
2550 // should correspond to TreeListCtrlIcon_xxx enum
2553 icons[0] = wxIcon(icon3_xpm); // closed
2554 icons[1] = wxIcon(icon3_xpm); // closed, selected
2555 icons[2] = wxIcon(icon5_xpm); // open
2556 icons[3] = wxIcon(icon5_xpm); // open, selected
2558 for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
2560 int sizeOrig = icons[i].GetWidth();
2561 if ( size == sizeOrig )
2563 images->Add(icons[i]);
2567 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
2571 mTreeListCtrl->AssignButtonsImageList(images);
2574 void WxGimmick::CreateButtonsImageList(int WXUNUSED(size))
2580 int WxGimmick::OnCompareItems(const wxTreeItemId& item1,
2581 const wxTreeItemId& item2)
2583 if ( m_reverseSort )
2585 // just exchange 1st and 2nd items
2586 return mTreeListCtrl->OnCompareItems(item2, item1);
2590 return mTreeListCtrl->OnCompareItems(item1, item2);
2595 void WxGimmick::DoToggleIcon(const wxTreeItemId& item)
2598 int image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_Folder)
2601 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Normal);
2603 image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_FolderSelected)
2604 ? TreeIcon_FileSelected
2605 : TreeIcon_FolderSelected;
2606 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Selected);
2609 void WxGimmick::LogEvent(const wxChar *name, const wxTreeEvent& event)
2611 wxTreeItemId item = event.GetItem();
2614 text << _T('"') << mTreeListCtrl->GetItemText(item).c_str() << _T('"');
2616 text = _T("invalid item");
2617 // wxLogMessage(wxT("%s(%s)"), name, text.c_str());
2622 #define TREE_EVENT_HANDLER(name) \
2623 void WxGimmick::name(wxTreeEvent& event) \
2625 /* LogEvent(_T(#name), event); */ \
2626 /* SetLastItem(mTreeListCtrl->wxTreeItemId()) *;*/ \
2630 TREE_EVENT_HANDLER(OnBeginRDrag)
2631 TREE_EVENT_HANDLER(OnDeleteItem)
2632 TREE_EVENT_HANDLER(OnGetInfo)
2633 TREE_EVENT_HANDLER(OnSetInfo)
2634 //TREE_EVENT_HANDLER(OnItemExpanded)
2635 TREE_EVENT_HANDLER(OnItemExpanding)
2636 //TREE_EVENT_HANDLER(OnItemCollapsed)
2637 //TREE_EVENT_HANDLER(OnSelChanged)
2638 // TREE_EVENT_HANDLER(OnSelChanging)
2641 void WxGimmick::OnItemCollapsed(wxTreeEvent& event)
2643 // std::cout << "* Collapsed *"<<std::endl;
2646 #undef TREE_EVENT_HANDLER
2648 void WxGimmick::OnTreeKeyDown(wxTreeEvent& event)
2651 // LogKeyEvent(wxT("Tree key down "), event.GetKeyEvent());
2652 std::cout << "* Key down *"<<std::endl;
2653 if (event.GetKeyCode()==WXK_RIGHT)
2655 std::cout << "Right"<<std::endl;
2656 wxTreeItemId itemId = mTreeListCtrl->GetSelection();
2659 std::cout << "item is ok"<<std::endl;
2660 wxPoint clientpt = event.GetPoint();
2661 wxPoint screenpt = ClientToScreen(clientpt);
2662 ShowMenu(itemId, clientpt);
2667 std::cout << "NOT Right"<<std::endl;
2672 void WxGimmick::OnBeginDrag(wxTreeEvent& event)
2674 wxTreeItemId id = event.GetItem();
2675 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2676 // std::cout << "OnBeginDrag("<<id<<")"<<std::endl;
2677 if (data->IsDatabase())
2679 // std::cout << "-- IS ROOT"<<std::endl;
2682 else if (data->IsDicomNode())
2684 // std::cout << "-- IS NODE"<<std::endl;
2687 // need to explicitly allow drag
2688 if ( event.GetItem() != GetDatabaseItem() )
2690 m_draggedItem = event.GetItem();
2692 wxPoint clientpt = event.GetPoint();
2693 wxPoint screenpt = ClientToScreen(clientpt);
2695 wxLogMessage(wxT("OnBeginDrag: started dragging %s at screen coords (%i,%i)"),
2696 GetItemText(m_draggedItem).c_str(),
2697 screenpt.x, screenpt.y);
2703 wxLogMessage(wxT("OnBeginDrag: this item can't be dragged."));
2708 void WxGimmick::OnEndDrag(wxTreeEvent& event)
2710 wxTreeItemId id = event.GetItem();
2711 // std::cout << "OnEndDrag("<<id<<")"<<std::endl;
2712 if (!id.IsOk()) return;
2713 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2714 if (data->IsDatabase())
2716 // std::cout << "-- IS ROOT"<<std::endl;
2718 else if (data->IsDicomNode())
2720 // std::cout << "-- IS NODE"<<std::endl;
2724 wxTreeItemId itemSrc = m_draggedItem,
2725 itemDst = event.GetItem();
2726 m_draggedItem = (wxTreeItemId)0l;
2728 // where to copy the item?
2729 if ( itemDst.IsOk() && !ItemHasChildren(itemDst) )
2731 // copy to the parent then
2732 itemDst = GetItemParent(itemDst);
2735 if ( !itemDst.IsOk() )
2737 wxLogMessage(wxT("OnEndDrag: can't drop here."));
2742 wxString text = GetItemText(itemSrc);
2743 wxLogMessage(wxT("OnEndDrag: '%s' copied to '%s'."),
2744 text.c_str(), GetItemText(itemDst).c_str());
2746 // just do append here - we could also insert it just before/after the item
2747 // on which it was dropped, but this requires slightly more work... we also
2748 // completely ignore the client data and icon of the old item but could
2749 // copy them as well.
2751 // Finally, we only copy one item here but we might copy the entire tree if
2752 // we were dragging a folder.
2753 int image = wxGetApp().ShowImages() ? TreeIcon_File : -1;
2754 AppendItem(itemDst, text, image);
2759 //====================================================================
2760 void WxGimmick::OnBeginLabelEdit(wxTreeEvent& event)
2762 // std::cout << "OnBeginLabelEdit"<<std::endl;
2763 wxTreeItemId id = event.GetItem();
2764 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2765 // If not a root : veto
2766 if (data->IsDatabase())
2773 //====================================================================
2775 //====================================================================
2776 void WxGimmick::OnEndLabelEdit(wxTreeEvent& event)
2778 // std::cout << "OnEndLabelEdit"<<std::endl;
2779 wxTreeItemId id = event.GetItem();
2780 TreeItemData *data = GetItemData(id);
2781 // If not a database : bug !
2782 if (data->IsDatabase())
2784 data->GetDicomNode()->GetDicomDatabase()->SetName(wx2std(event.GetLabel()));
2785 mFieldsView->UpdateValues(data->GetDicomNode());
2789 std::cerr<< "!!!! Internal error : send bug report !!!!"<<std::endl;
2792 //====================================================================
2795 void WxGimmick::OnItemCollapsing(wxTreeEvent& event)
2797 // wxLogMessage(wxT("OnItemCollapsing"));
2799 // for testing, prevent the user from collapsing the first child folder
2800 wxTreeItemId itemId = event.GetItem();
2803 if ( IsTestItem(itemId) )
2805 wxMessageBox(wxT("You can't collapse this item."));
2813 //====================================================================
2814 void WxGimmick::ShowHelp()
2819 mHelpWindow = new WxGimmickHelpWindow(this);
2821 mHelpWindow->CenterOnParent();
2822 mHelpWindow->ShowModal();
2825 //====================================================================
2831 //================================================================
2832 //================================================================
2833 //================================================================
2834 //================================================================
2835 //================================================================
2837 //================================================================
2838 //================================================================
2839 //================================================================
2840 //================================================================
2841 //================================================================
2847 // ----------------------------------------------------------------------------
2849 // ----------------------------------------------------------------------------
2851 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_DRAG)
2852 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_RDRAG)
2853 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_DELETE_ITEM)
2854 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_GET_INFO)
2855 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SET_INFO)
2856 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDED)
2857 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDING)
2858 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSED)
2859 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSING)
2862 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT)
2863 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_LABEL_EDIT)
2866 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED)
2867 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGING)
2868 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_KEY_DOWN)
2869 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU)
2870 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_ITEM_STYLE_CHANGED)
2872 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_ACTIVATED)
2873 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK)
2874 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK)
2875 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_DRAG)
2876 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK)
2877 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP)
2878 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MENU)
2880 // ----------------------------------------------------------------------------
2882 // ----------------------------------------------------------------------------
2884 IMPLEMENT_ABSTRACT_CLASS(WxGimmickEvent, wxNotifyEvent)
2887 WxGimmickEvent::WxGimmickEvent(wxEventType commandType,
2889 const wxTreeItemId& item)
2891 wxNotifyEvent(commandType, tree->GetId()),
2895 // m_editCancelled = false;
2897 SetEventObject(tree);
2900 SetClientObject(tree->mTreeListCtrl->GetItemData(item));
2903 WxGimmickEvent::WxGimmickEvent(wxEventType commandType, int id)
2905 wxNotifyEvent(commandType, id),
2909 // m_editCancelled = false;
2912 WxGimmickEvent::WxGimmickEvent(const WxGimmickEvent & event)
2914 wxNotifyEvent(event),
2918 m_evtKey = event.m_evtKey;
2919 m_item = event.m_item;
2920 m_itemOld = event.m_itemOld;
2921 mColor = event.mColor;
2922 mUserData = event.mUserData;
2923 // m_pointDrag = event.m_pointDrag;
2924 // m_label = event.m_label;
2925 // m_editCancelled = event.m_editCancelled;
2935 //================================================================
2936 //================================================================
2937 //================================================================
2938 //================================================================
2939 //================================================================
2940 WxGimmickFrame::WxGimmickFrame( wxWindow *parent,
2943 : wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size)
2945 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
2946 mWxGimmick = new WxGimmick(this,-1,
2949 sizer->Add(mWxGimmick,1,wxGROW);
2951 SetAutoLayout(true);
2954 //================================================================
2956 //================================================================
2957 WxGimmickFrame::~WxGimmickFrame()
2960 //================================================================
2962 //================================================================
2963 void WxGimmickFrame::OnSelChanged(WxGimmickEvent& event)
2965 // std::cout << "+++++ WxGimmickFrame::OnSelChanged ++++++++++"
2967 std::vector<std::string> file;
2968 // mWxGimmick->GetSelectedImages(file);
2970 std::vector<std::string>::iterator i;
2971 for (i=file.begin();i!=file.end();++i)
2973 std::cout << "'" << *i << "'" << std::endl;
2975 std::cout << "++++++++++++++++++++" << std::endl;
2978 //================================================================
2980 //================================================================
2981 BEGIN_EVENT_TABLE(WxGimmickFrame, wxFrame)
2982 EVT_TREEVIEWLIST_SEL_CHANGED(-1,WxGimmickFrame::OnSelChanged)
2984 //================================================================