2 #include <creaImageIOWxGimmick.h>
3 #include <creaImageIODicomNodeComparators.h>
5 #include <creaMessageManager.h>
7 #include "icons/database.xpm"
8 #include "icons/folder.xpm"
9 #include "icons/dicomdir.xpm"
10 #include "icons/patient.xpm"
11 #include "icons/study.xpm"
12 #include "icons/series.xpm"
13 #include "icons/image.xpm"
14 #include "icons/root.xpm"
15 #include <wx/filedlg.h>
16 #include <wx/dirdlg.h>
19 #include <vtkCamera.h>
20 #include <vtkRenderer.h>
22 #include <wx/filefn.h>
23 //#include <wx/tipwin.h>
27 #include <boost/filesystem.hpp>
28 #include <boost/algorithm/string.hpp>
32 //================================================================
33 const int WxGimmick::UserMenuFirstId = 1000;
34 //================================================================
36 //================================================================
49 //================================================================
51 //================================================================
54 PopUp_NewCollection = 100,
55 PopUp_OpenCollection = 101,
56 PopUp_CloseCollection = 102,
57 PopUp_DeleteCollection = 103,
58 PopUp_AddDirectory = 110,
60 PopUp_AddRawFile = 112,
65 PopUp_User = WxGimmick::UserMenuFirstId,
67 //================================================================
69 //================================================================
70 #define TreeListCtrlId 10000
71 //================================================================
73 //================================================================
74 const icon_id Icon[5] = { Icon_Database,
79 //================================================================
82 //================================================================
83 class WxGimmickDicomNodeData : public DicomNodeData
86 WxGimmickDicomNodeData
87 (WxGimmickTreeItemData* d = 0) :
91 ~WxGimmickDicomNodeData();
93 WxGimmickTreeItemData* GetTreeItemData()
94 { return mTreeItemData; }
95 void SetTreeItemData( WxGimmickTreeItemData* d)
96 { mTreeItemData = d; }
97 inline bool IsLoaded() { return mLoaded; }
98 inline void SetLoaded(bool v) { mLoaded = v; }
101 WxGimmickTreeItemData* mTreeItemData;
104 //================================================================
107 //================================================================
108 class WxGimmickTreeItemData : public wxTreeItemData
111 WxGimmickTreeItemData(DicomNode* node)
121 WxGimmickDicomNodeData* data =
122 node->GetData<WxGimmickDicomNodeData*>();
125 if (data->GetTreeItemData()!=0)
127 std::cout << "WxGimmickTreeItemData ERROR ****"
131 data->SetTreeItemData(this);
134 node->SetData( new WxGimmickDicomNodeData(this) );
135 if (node->GetType()==DicomNode::Database)
145 ~WxGimmickTreeItemData()
149 WxGimmickDicomNodeData* data =
150 mDicomNode->GetData<WxGimmickDicomNodeData*>();
151 if (data) data->SetTreeItemData(0);
155 inline void ResetDicomNode()
160 inline void SetItemId ( const wxTreeItemId& item ) { mItemId = item; }
161 inline const wxTreeItemId& GetItemId() const { return mItemId; }
163 inline bool IsDefault() const { return (mType == 0); }
164 inline bool IsDatabase() const { return (mType == 2); }
165 inline bool IsDicomNode() const { return (mType == 1); }
167 inline DicomNode* GetDicomNode() { return mDicomNode; }
168 inline long& UpdateTime() { return mUpdateTime; }
169 inline bool IsLoaded()
171 mDicomNode->GetData<WxGimmickDicomNodeData*>()->IsLoaded();
173 inline void SetLoaded(bool v)
175 mDicomNode->GetData<WxGimmickDicomNodeData*>()->SetLoaded(v);
178 inline int GetUserFlags() const { return mUserFlags; }
179 inline void SetUserFlags(int f) { mUserFlags = f; }
182 // The type of item :
185 // 2 = DicomNode of type Database
187 wxTreeItemId mItemId;
188 DicomNode* mDicomNode;
193 //================================================================
196 //================================================================
197 WxGimmickDicomNodeData::~WxGimmickDicomNodeData()
201 mTreeItemData->ResetDicomNode();
204 //================================================================
239 //================================================================
240 //================================================================
241 //================================================================
242 //================================================================
243 //================================================================
244 //================================================================
245 //================================================================
246 WxGimmick::WxGimmick(wxWindow *parent,
252 : wxPanel(parent,id,pos,size),
253 mSelectionType(image_type),
254 mSaveConfigurationOnClose(true),
257 // Initialize image size corresponding to current selection
258 switch (mSelectionType)
260 case GIMMICK_2D_IMAGE_SELECTION : mSelectionMaxImageDimension = 2; break;
261 case GIMMICK_3D_IMAGE_SELECTION : mSelectionMaxImageDimension = 3; break;
262 case GIMMICK_4D_IMAGE_SELECTION : mSelectionMaxImageDimension = 4; break;
263 default : mSelectionMaxImageDimension = 0;
267 // Start the threads ...
271 SetDatabaseExtension("sqlite3");
272 // Create the UserSettings dir if does not exist
273 CreateUserSettingsDirectory();
274 // Sets the current directory to the Setting dir
275 mCurrentDirectory = std2wx(GetUserSettingsDirectory());
277 // Window layout creation
278 wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
281 mSplitter1 = new wxSplitterWindow( this, -1);
283 // TreeCtrl on the left
288 //| wxTR_LINES_AT_ROOT
289 | wxTR_FULL_ROW_HIGHLIGHT
296 | wxTR_EDIT_LABELS //Use this style if you wish the user to be able to edit labels in the tree list control.
297 //wxTR_NO_BUTTONS For convenience to document that no buttons are to be drawn.
298 | wxTR_HAS_BUTTONS //Use this style to show + and - buttons to the left of parent items.
299 | wxTR_TWIST_BUTTONS //Use this style to show Mac-style twister buttons to the left of parent items. If both wxTR_HAS_BUTTONS and wxTR_TWIST_BUTTONS are given, twister buttons are generated.
300 //wxTR_NO_LINES Use this style to hide vertical level connectors.
301 | wxTR_FULL_ROW_HIGHLIGHT //Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree list control window. (This flag is ignored under Windows unless you specify wxTR_NO_LINES as well.)
302 | wxTR_LINES_AT_ROOT //Use this style to show lines between root nodes. Only applicable if wxTR_HIDE_ROOT is set and wxTR_NO_LINES is not set.
303 | wxTR_HIDE_ROOT //Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes.
304 // wxTR_ROW_LINES // Use this style to draw a contrasting border between displayed rows.
305 // wxTR_HAS_VARIABLE_ROW_HEIGHT// Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset.
306 // wxTR_SINGLE For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default.
307 | wxTR_MULTIPLE // Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected.
308 | wxTR_EXTENDED // Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases.)
309 //wxTR_DEFAULT_STYLE The set of flags that are closest to the defaults for the native control for a particular toolkit.
310 //| wxTR_VIRTUAL //The application provides items text on demand.
313 mTreeListCtrl = new wxTreeListCtrl(mSplitter1,
319 mTreeListCtrl->SetIndent(0);
320 mTreeListCtrl->SetLineSpacing(5);
325 wxPanel *rpanel = new wxPanel( mSplitter1, -1 );
327 wxBoxSizer *rsizer = new wxBoxSizer(wxHORIZONTAL);
328 // Right panel top/bottom split
329 mSplitter2 = new wxSplitterWindow( rpanel , -1);
332 mPanelImage = new wxPanel(mSplitter2,-1);
333 mPanelImage->SetBackgroundColour( wxColour(0,0,0) );
335 wxBoxSizer *isizer = new wxBoxSizer(wxHORIZONTAL );
336 mPanelImage->SetSizer( isizer );
339 mwxNotebook = new wxNotebook(mSplitter2,
340 -1,wxDefaultPosition, wxDefaultSize, 0);
344 // Fields view (bottom)
345 mFieldsView = new WxGimmickFieldsView(mwxNotebook,-1,
349 mFieldsView->SetColors
350 ( GetSettings().Colour(DicomNode::Database),
351 GetSettings().BgColour(DicomNode::Database),
352 GetSettings().Colour(DicomNode::Patient),
353 GetSettings().BgColour(DicomNode::Patient),
354 GetSettings().Colour(DicomNode::Study),
355 GetSettings().BgColour(DicomNode::Study),
356 GetSettings().Colour(DicomNode::Series),
357 GetSettings().BgColour(DicomNode::Series),
358 GetSettings().Colour(DicomNode::Image),
359 GetSettings().BgColour(DicomNode::Image));
360 mwxNotebook->AddPage( mFieldsView, _T("Dicom fields"));
363 mHelp = new WxGimmickHelp(mwxNotebook);
364 mwxNotebook->AddPage( mHelp, _T("Help"));
367 int wsize = size.GetWidth();
368 int hsize = size.GetHeight();
369 int previewhsize = 150;
370 int previewwsize = 400;
372 mSplitter2->SetMinimumPaneSize( previewhsize );
373 mSplitter2->SplitHorizontally( mPanelImage, mwxNotebook, //mFieldsView,
374 hsize - previewhsize);
376 rsizer->Add( mSplitter2,1,wxGROW ,0);
378 rpanel->SetAutoLayout(true);
379 rpanel->SetSizer( rsizer );
383 mInteractor = new crea::creawxVTKRenderWindowInteractor(mPanelImage,-1);
384 mInteractor->UseCaptureMouseOn();
386 mViewer = vtkImageViewer2::New();
387 mViewer->SetupInteractor ( mInteractor );
388 mViewer->SetInput(mReader.GetImage(""));
390 isizer-> Add( mInteractor ,1,wxGROW ,0);
392 topsizer->Add( mSplitter1,1,wxGROW ,0);
395 mSplitter1->SetMinimumPaneSize( 200 );
396 mSplitter1->SplitVertically(mTreeListCtrl,
398 wsize - previewwsize );
401 // ProcessImageEvents();
402 SetSizer( topsizer );
405 mDatabaseListFile = GetUserSettingsDirectory();
406 mDatabaseListFile += "collections.txt";
411 ShowImage(mReader.GetImage(""));
413 // Show help if no collection
414 if (GetDicomDatabaseList().size()==0)
416 mwxNotebook->SetSelection(1);
420 mwxNotebook->SetSelection(0);
422 // mJustStarted = true;
424 //================================================================
428 #define VALID_FILE_SEPARATOR "\\"
429 #define INVALID_FILE_SEPARATOR "/"
431 #define INVALID_FILE_SEPARATOR "\\"
432 #define VALID_FILE_SEPARATOR "/"
435 //================================================================
436 const std::string& WxGimmick::GetUserSettingsDirectory()
438 if (mUserSettingsDirectory.size()==0)
440 #if defined(__GNUC__)
441 mUserSettingsDirectory = getenv("HOME");
442 #elif defined(_WIN32)
443 mUserSettingsDirectory = getenv("USERPROFILE");
445 mUserSettingsDirectory += "/.gimmick/";
446 boost::algorithm::replace_all( mUserSettingsDirectory,
447 INVALID_FILE_SEPARATOR ,
448 VALID_FILE_SEPARATOR);
450 return mUserSettingsDirectory;
452 //================================================================
454 //========================================================================
455 void WxGimmick::CreateUserSettingsDirectory()
457 if (! boost::filesystem::is_directory( GetUserSettingsDirectory() ) )
459 creaMessage("Gimmick!",1,"==> Directory '"<<GetUserSettingsDirectory()<<"' "
460 << "does not exist : creating it"<<std::endl);
462 if ( ! boost::filesystem::create_directory( GetUserSettingsDirectory() ) )
464 creaMessage("Gimmick!",1,"!! ERROR CREATING '"<<GetUserSettingsDirectory()<<"'");
468 //========================================================================
470 //================================================================
471 WxGimmick::~WxGimmick()
473 // std::cout << "WxGimmick::~WxGimmick()" <<std::endl;
474 if (mSaveConfigurationOnClose) SaveConfiguration();
477 // std::cout << "Reader stopped"<<std::endl;
479 DicomDatabaseListType::iterator i;
480 for (i =GetDicomDatabaseList().begin();
481 i!=GetDicomDatabaseList().end();
489 //================================================================
492 //================================================================
493 void WxGimmick::RebuildView()
497 mTreeListCtrl->DeleteRoot(); //DeleteAllItems();
498 // mTreeDefaultItemId = wxTreeItemId();
501 int nbattr = mSettings.GetMaxNumberOfColumns();
503 for (int j=0;j<nbattr; j++)
505 mTreeListCtrl->AddColumn (_T(""),
506 200, //DEFAULT_COL_WIDTH,
512 mTreeListCtrl->SetMainColumn (0);
513 mTreeListCtrl->SetColumnEditable (0, true);
515 mTreeRootId = mTreeListCtrl->AddRoot( _T(""),Icon_Root,Icon_Root);
517 // The collections columns legends
518 mCollectionsTitlesItemId =
519 CreateChildrenColumnsTitles(mTreeRootId,DicomNode::Database);
521 DicomDatabaseListType::iterator i;
522 for (i =GetDicomDatabaseList().begin();
523 i!=GetDicomDatabaseList().end();
526 UpdateDicomDatabaseView(*i);
529 mTreeListCtrl->Expand(mTreeRootId);
531 // mTreeListCtrl->ExpandAll(mTreeRootId);
532 // std::cout << "EO RebuildAll"<<std::endl;
534 //================================================================
538 //================================================================
539 void WxGimmick::UpdateDicomDatabaseView(DicomDatabase* db)
545 // Does the db exist ?
546 wxTreeItemIdValue cookie;
547 for (dbid = mTreeListCtrl->GetFirstChild(mTreeRootId,cookie);
549 dbid = mTreeListCtrl->GetNextChild(mTreeRootId,cookie))
551 data = (TreeItemData *)mTreeListCtrl->GetItemData(dbid);
552 if ((data->IsDatabase())&&(data->GetDicomNode()==db)) break;
555 // Not found : create
559 int iconid = Icon[DicomNode::Database];
562 // std::cout << " -> Creating item for '"<<db->GetLabel()<<"'"<<std::endl;
563 data = new TreeItemData(db);
564 dbid = mTreeListCtrl->AppendItem( mTreeRootId,
565 std2wx(db->GetLabel()),
569 data->SetItemId(dbid);
570 mTreeListCtrl->SetItemTextColour
571 (dbid,mSettings.Colour(DicomNode::Database));
572 mTreeListCtrl->SetItemBackgroundColour
573 (dbid,mSettings.BgColour(DicomNode::Database));
575 // The patients columns legends
576 CreateChildrenColumnsTitles(dbid,DicomNode::Patient);
579 // Increase UpdateTime to detect obsolete items after
581 data->UpdateTime()++;
583 DicomNode::ChildrenListType::iterator j;
584 for (j= db->GetChildrenList().begin();
585 j!=db->GetChildrenList().end();
588 UpdateDicomNodeView(*j,dbid);
591 DeleteObsoleteChildren(dbid);
593 mTreeListCtrl->EnsureVisible(dbid);
596 //================================================================
598 //================================================================
599 void WxGimmick::UpdateDicomNodeView(DicomNode* n,
600 const wxTreeItemId& parent)
604 // std::cout << "* UpdateDicomNodeView("<<n->GetLabel()<<")"<<std::endl;
606 wxTreeItemId newparent = parent;
609 if ((!mSettings.MergeStudySeries()) ||
610 (n->GetType() != DicomNode::Study))
612 // Does the item exist ?
613 wxTreeItemIdValue cookie;
614 for (newparent = mTreeListCtrl->GetFirstChild(parent,cookie);
616 newparent = mTreeListCtrl->GetNextChild(parent,cookie))
618 data = (TreeItemData *)mTreeListCtrl->GetItemData(newparent);
619 if (data->GetDicomNode() == n) break;
621 // Not found : create
622 if (!newparent.IsOk())
624 int image(Icon[n->GetType()]);
625 wxColour *colour(&mSettings.Colour(n->GetType()));
626 wxColour *bgcolour(&mSettings.BgColour(n->GetType()));
628 if (n->GetType()==DicomNode::Image)
630 // std::cout << "!!!Image"<<std::endl;
631 if (n->GetData<NodeData*>()!=0)
633 // std::cout << ">> n->GetData<NodeData*>()!=0" << std::endl;
634 if (n->GetData<NodeData*>()->IsLoaded())
636 colour = &mSettings.LoadedImageColour();
638 // std::cout << "<< n->GetData<NodeData*>()!=0" << std::endl;
642 data = new TreeItemData(n);
643 newparent = mTreeListCtrl->AppendItem(parent,
647 data->SetItemId(newparent);
648 mTreeListCtrl->SetItemTextColour(newparent,*colour);
649 mTreeListCtrl->SetItemBackgroundColour(newparent,*bgcolour);
651 UpdateColumns(newparent);
654 if (n->GetType()!=DicomNode::Image)
656 CreateChildrenColumnsTitles(newparent,n->GetType()+1);
662 UpdateColumns(newparent,true);
665 // synchonise update time with parent
666 TreeItemData * parent_data =
667 (TreeItemData *)mTreeListCtrl->GetItemData(parent);
668 data->UpdateTime() = parent_data->UpdateTime();
671 DicomNode::ChildrenListType::iterator i;
672 for (i=n->GetChildrenList().begin();
673 i!=n->GetChildrenList().end();
676 UpdateDicomNodeView(*i,newparent);
679 if (n->GetType() != DicomNode::Image)
680 DeleteObsoleteChildren(newparent);
683 //================================================================
685 //================================================================
686 void WxGimmick::UpdateColumns(wxTreeItemId& item,
690 (TreeItemData *)mTreeListCtrl->GetItemData(item);
691 DicomNode* node = data->GetDicomNode();
695 // Update only the first field (for #children update)
696 DicomNode* node2 = node;
697 // If Study and Series level are merged and node type is Series
698 // then have to get back to the Study level
699 if ((mSettings.MergeStudySeries())&&
700 (node->GetType() == DicomNode::Series))
701 node2 = node->GetParent();
704 lab += node2->GetFieldValueMap()
705 [ mSettings.GetColumnList(node2->GetType())[0].Key ];
707 if (node->GetType() != DicomNode::Image)
709 if (node->GetChildrenList().size()>0)
712 sprintf(sz," [%d]",node->GetNumberOfChildren());
716 mTreeListCtrl->SetItemText(item,std2wx(lab));
722 Settings::ColumnListType::iterator col;
723 // If Study and Series level are merged and node type is Series
724 // then have to fill the Study level cols first
725 if ((mSettings.MergeStudySeries())&&
726 (node->GetType() == DicomNode::Series))
728 DicomNode* node2 = node->GetParent();
729 for (col = mSettings.GetColumnList(node2->GetType()).begin();
730 col != mSettings.GetColumnList(node2->GetType()).end();
733 std::string s = node2->GetFieldValueMap()[col->Key];
738 sprintf(sz," [%d]",node->GetNumberOfChildren());
741 mTreeListCtrl->SetItemText (item, c, std2wx(s));
746 for (col = mSettings.GetColumnList(node->GetType()).begin();
747 col != mSettings.GetColumnList(node->GetType()).end();
750 std::string s = node->GetFieldValueMap()[col->Key];
751 if ((c==0)&&(node->GetType() != DicomNode::Image))
754 sprintf(sz," [%d]",node->GetNumberOfChildren());
757 mTreeListCtrl->SetItemText (item, c, std2wx(s));
763 //================================================================
765 //================================================================
766 wxTreeItemId WxGimmick::CreateChildrenColumnsTitles
770 // Creates the sub-level columns titles
772 = new TreeItemData(0);
773 wxTreeItemId id = mTreeListCtrl->AppendItem( item,
779 mTreeListCtrl->SetItemFont(id, *wxITALIC_FONT);
780 mTreeListCtrl->SetItemTextColour(id, mSettings.Colour(t));
781 mTreeListCtrl->SetItemBackgroundColour(id, mSettings.BgColour(t));
782 UpdateColumnsTitles(id,t);
785 //================================================================
787 //================================================================
788 void WxGimmick::UpdateColumnsTitles(wxTreeItemId& item,
791 // std::cout << "Update columns titles "<<t<<std::endl;
793 Settings::ColumnListType::iterator col;
794 for (col = mSettings.GetColumnList(t).begin();
795 col != mSettings.GetColumnList(t).end();
798 // std::cout << col->Name << std::endl;
799 mTreeListCtrl->SetItemText (item, c, std2wx(col->Name));
803 //================================================================
806 //================================================================
807 void WxGimmick::DeleteObsoleteChildren(wxTreeItemId& id)
810 TreeItemData * parent_data =
811 (TreeItemData *)mTreeListCtrl->GetItemData(id);
814 wxTreeItemIdValue cookie;
815 std::vector<wxTreeItemId> children;
816 for (child = mTreeListCtrl->GetFirstChild(id,cookie);
818 child = mTreeListCtrl->GetNextChild(id,cookie))
820 children.push_back(child);
822 std::vector<wxTreeItemId>::iterator i;
823 for (i=children.begin();i!=children.end();++i)
826 (TreeItemData *)mTreeListCtrl->GetItemData(*i);
828 ((data->GetDicomNode()>0) &&
829 ((data->UpdateTime() != parent_data->UpdateTime()))) ||
830 ((data->IsDicomNode()) &&
831 (data->GetDicomNode()==0))
834 // std::cout << "DOBSC="<<mTreeListCtrl->GetItemText(*i)<<std::endl;
835 mTreeListCtrl->Delete(*i);
839 //================================================================
841 //================================================================
842 void WxGimmick::OpenOrNewDatabase(bool open)
846 long style = wxFD_SAVE | wxFD_OVERWRITE_PROMPT;
847 if (open) style = wxOPEN | wxFILE_MUST_EXIST;
848 std::string wc("*.");
849 wc += GetDatabaseExtension();
851 // TO DO : Handler give their wildcards
852 wxFileDialog* FD = new wxFileDialog( 0,
860 if (FD->ShowModal()!=wxID_OK) return;
862 std::string filename = wx2std (FD->GetPath());
863 mCurrentDirectory = FD->GetDirectory();
867 boost::filesystem::path filepath(filename);
868 boost::filesystem::change_extension(filepath,GetDatabaseExtension());
869 if ( boost::filesystem::exists(filepath) )
871 boost::filesystem::remove(filepath);
873 LG : works on Linux but not Windows :
874 if ( ! boost::filesystem::remove(filepath) )
876 wxMessageBox(_T("Could not overwrite ")
877 +std2wx(filepath.string()),
888 DicomDatabase* db = new DicomDatabase(filename);
895 wxMessageBox(_T("An error occured while opening ")
905 wxGetTextFromUser(_T("Enter collection name"),_T("New collection"),
907 db->SetName(wx2std(collname));
912 wxMessageBox(_T("An error occured while creating ")
920 if (GetDicomDatabaseList().size()==0) mFieldsView->UpdateFields(db);
921 GetDicomDatabaseList().push_back(db);
922 UpdateDicomDatabaseView(db);
926 //================================================================
929 //================================================================
930 void WxGimmick::LoadConfiguration()
933 // std::cout << "WxGimmick : Reading config"<<std::endl;
935 // std::cout << "==> Loading collections from '"<<mDatabaseListFile
939 s.open(mDatabaseListFile.c_str());
946 if (str.size()==0) continue;
948 std::vector<std::string> tokens;
949 boost::split( tokens, str, boost::is_any_of("\t") );
951 DicomDatabase* db = new DicomDatabase(tokens[0]);
953 // std::cout << " -> Loading collection '"<<tokens[0]<<"'"<<std::endl;
955 if (tokens.size()==2)
957 db->SetName(tokens[1]);
962 GetDicomDatabaseList().push_back(db);
963 db->DBLoadChildren(db,DicomNode::Patient);
964 if (mSettings.HasActiveComparator(DicomNode::Patient))
967 ( mSettings.GetActiveComparator(DicomNode::Patient) );
972 // std::cout << " ... ERROR !"<<std::endl;
980 std::cout << "ERROR opening "<<mDatabaseListFile<<std::endl;
984 mTreeListCtrl->SetBackgroundColour(mSettings.BgColour(DicomNode::Database));
985 if (GetDicomDatabaseList().begin() !=
986 GetDicomDatabaseList().end() )
988 mFieldsView->UpdateFields(*GetDicomDatabaseList().begin());
994 //================================================================
996 //================================================================
997 void WxGimmick::SaveConfiguration()
1000 creaMessage("Gimmick!",1,"Gimmick! : Saving configuration..."<<std::endl);
1002 creaMessage("Gimmick!",1,"Gimmick! : ==> Saving collections in '"
1003 <<mDatabaseListFile<<"'"<<std::endl);
1006 s.open(mDatabaseListFile.c_str());
1009 creaError("Gimmick! : error opening '"<<mDatabaseListFile<<"'");
1012 DicomDatabaseListType::iterator i;
1013 for (i =GetDicomDatabaseList().begin();
1014 i!=GetDicomDatabaseList().end();
1017 s << (*i)->GetFileName() << "\t";
1018 s << (*i)->GetName() << std::endl;
1024 //================================================================
1027 //================================================================
1028 void WxGimmick::OnClose(wxCloseEvent& event)
1030 if (mSaveConfigurationOnClose) SaveConfiguration();
1032 //================================================================
1034 //================================================================
1035 void WxGimmick::OnItemActivated(wxTreeEvent& event)
1041 // std::cout << "OnItemActivated" <<std::endl;
1042 wxTreeItemId itemId = event.GetItem();
1043 if (mTreeListCtrl->IsExpanded(itemId))
1045 mTreeListCtrl->Collapse(itemId);
1049 mTreeListCtrl->Expand(itemId);
1052 //================================================================
1054 //================================================================
1055 void WxGimmick::LoadChildren(wxTreeItemId& id)
1057 TreeItemData *item = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1060 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1061 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1064 // If children not already loaded : do it
1066 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1067 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1070 // Some new children loaded
1072 if (mSettings.HasActiveComparator
1073 (item->GetDicomNode()->GetType()+1))
1075 /* std::cout << "Sorting using '"
1076 << mSettings.GetActiveComparator
1077 (item->GetDicomNode()->GetType()+1).GetName()
1080 item->GetDicomNode()->SortChildren
1081 ( mSettings.GetActiveComparator
1082 (item->GetDicomNode()->GetType()+1)
1084 // std::cout << "ok"<<std::endl;
1087 DicomNode::ChildrenListType::iterator i;
1088 for (i=item->GetDicomNode()->GetChildrenList().begin();
1089 i!=item->GetDicomNode()->GetChildrenList().end();
1092 UpdateDicomNodeView(*i,id);
1095 // EO If children not already loaded
1099 //================================================================
1102 //================================================================
1103 void WxGimmick::OnItemExpanded(wxTreeEvent& event)
1106 // std::cout << "* Expanded *"<<std::endl;
1111 wxTreeItemId itemId = event.GetItem();
1112 LoadChildren(itemId);
1116 // expand if collapsed and collapse if expanded ...
1117 TreeItemData *item =
1118 (TreeItemData *)mTreeListCtrl->GetItemData(itemId);
1121 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1122 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1125 // If children not already loaded : do it
1127 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1128 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1132 // Some new children loaded
1134 if (mSettings.HasActiveComparator
1135 (item->GetDicomNode()->GetType()+1))
1137 /* std::cout << "Sorting using '"
1138 << mSettings.GetActiveComparator
1139 (item->GetDicomNode()->GetType()+1).GetName()
1142 item->GetDicomNode()->SortChildren
1143 ( mSettings.GetActiveComparator
1144 (item->GetDicomNode()->GetType()+1)
1146 // std::cout << "ok"<<std::endl;
1149 // If images : sort them
1150 if (item->IsDicomNode())
1152 if (item->GetDicomNode()->GetType()==DicomNode::Series)
1156 LexicographicalDicomNodeComparator compare;
1157 // DicomNodeImageImageNumberComparator c1;
1159 DicomNodeImageSliceLocationComparator c1;
1160 DicomNodeImageImageNumberComparator c2;
1161 DicomNodeImageFileNameComparator cn;
1165 // std::cout << "SORT"<<std::endl;
1166 item->GetDicomNode()->SortChildren(compare);
1167 // std::cout << "EO SORT"<<std::endl;
1175 DicomNode::ChildrenListType::iterator i;
1176 for (i=item->GetDicomNode()->GetChildrenList().begin();
1177 i!=item->GetDicomNode()->GetChildrenList().end();
1180 UpdateDicomNodeView(*i,itemId);
1183 // EO If children not already loaded
1186 // mTreeListCtrl->Expand(itemId);
1189 //================================================================
1193 //=====================================================================
1194 void WxGimmick::InsertRoot(wxTreeItemId& id, Root* r)
1197 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1202 data->GetDicomNode()->GetDicomDatabase()->LoadAll();
1203 printf(">>>>>> Time to load all = %ldms \n",sw.Time());
1205 UpdateRootView(data->GetDicomNode()->GetDicomDatabase());
1208 if (data->IsDicomNode())
1211 r->Insert(data->GetDicomNode());
1212 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1215 else if (data->IsDatabase())
1218 DicomNode::ChildrenListType::iterator j;
1219 for (j= data->GetDicomNode()->GetChildrenList().begin();
1220 j!=data->GetDicomNode()->GetChildrenList().end();
1225 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1231 //=====================================================================
1235 //=================================================
1236 void WxGimmick::DeleteDicomDatabase(wxTreeItemId& id,
1240 DicomDatabaseListType::iterator i = find(GetDicomDatabaseList().begin(),
1241 GetDicomDatabaseList().end(),
1244 GetDicomDatabaseList().erase(i);
1245 mTreeListCtrl->Delete(id);
1247 //=================================================
1251 //=====================================================================
1253 void WxGimmick::OnItemRightClick(wxTreeEvent& event)
1256 wxTreeItemId itemId = event.GetItem();
1259 wxPoint clientpt = event.GetPoint();
1260 wxPoint screenpt = ClientToScreen(clientpt);
1261 ShowMenu(itemId, clientpt);
1265 //=====================================================================
1269 //=====================================================================
1270 void WxGimmick::ShowMenu(wxTreeItemId id, const wxPoint& pt)
1273 // std::cout << "ShowMenu" <<std::endl;
1275 TreeItemData *data =
1276 (TreeItemData *)mTreeListCtrl->GetItemData(id);
1282 title << wxT("Menu for ") << mTreeListCtrl->GetItemText(id);
1286 title = wxT("Menu for no particular item");
1293 if (id==mCollectionsTitlesItemId)
1295 menu.Append(PopUp_NewCollection, _T("&New collection"));
1296 menu.Append(PopUp_OpenCollection, _T("&Open collection"));
1300 if (data->IsDatabase())
1302 wxMenu* addmenu = new wxMenu;
1303 addmenu->Append(PopUp_AddDirectory, _T("Scan &Directory"));
1304 addmenu->Append(PopUp_AddFile, _T("Select &File(s)"));
1305 // addmenu->Append(PopUp_AddRawFile, _T("Add &Raw image"));
1306 menu.AppendSubMenu(addmenu, _T("&Add image(s) to collection..."));
1307 menu.Append(PopUp_CloseCollection, _T("&Close collection"));
1308 menu.Append(PopUp_DeleteCollection, _T("&Delete collection"));
1310 if (data->IsDicomNode())
1315 std::string str("&Remove ");
1316 str += data->GetDicomNode()->GetTypeName();
1317 menu.Append(PopUp_Remove, std2wx(str));
1321 if ((data->GetDicomNode()>0)&&
1322 ( data->GetDicomNode()->GetType()<DicomNode::Image))
1324 int ctype = data->GetDicomNode()->GetType()+1;
1325 if (mSettings.HasActiveComparator(ctype))
1327 wxMenu* sortmenu = new wxMenu;
1329 Settings::ComparatorsList::iterator i;
1330 for (i =mSettings.GetComparatorsList(ctype).begin();
1331 i !=mSettings.GetComparatorsList(ctype).end();
1334 sortmenu->AppendRadioItem(PopUp_Sort+n, std2wx(i->GetName()));
1338 sortmenu->Check(PopUp_Sort+
1339 mSettings.GetActiveComparatorIndex(ctype)
1342 std::string sortmenustr("&Sort ");
1343 sortmenustr += DicomNode::GetPluralTypeName(ctype);
1344 sortmenustr += " by...";
1345 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1346 menu.AppendSubMenu(sortmenu,std2wx(sortmenustr));
1349 item->GetDicomNode()->SortChildren
1350 ( mSettings.GetActiveComparator
1351 (item->GetDicomNode()->GetType()+1)
1353 std::cout << "ok"<<std::endl;
1358 // Event : user can customize the menu
1360 ev(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU,this,id);
1364 ev.SetDicomNode(data->GetDicomNode());
1366 GetEventHandler()->ProcessEvent(ev);
1369 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1370 menu.Append(PopUp_Settings, wxT("&Settings..."));
1371 menu.Append(PopUp_About, wxT("&About..."));
1376 wxMenu* newmenu = new wxMenu;
1377 wxMenu* openmenu = new wxMenu;
1378 Tree::RootHandlerListType::iterator h;
1380 for (h= Tree::GetRootHandlerList().begin();
1381 h!=Tree::GetRootHandlerList().end();
1384 if ((*h)->SupportsNew())
1386 newmenu->Append(PopUp_New+i, std2wx((*h)->GetName()));
1388 if ((*h)->SupportsOpen())
1389 openmenu->Append(PopUp_Open+i, std2wx((*h)->GetName()));
1393 menu.AppendSubMenu(openmenu, _T("&Open"));
1394 menu.AppendSubMenu(newmenu, _T("&New"));
1398 if ((data->IsDatabase())||(data->IsDicomNode()))
1400 Root* itroot = data->GetDicomNode()->GetDicomDatabase();
1401 // if (!itroot) itroot = data->GetDicomNode()->GetRoot();
1402 wxMenu* insertmenu = new wxMenu;
1403 bool hasone = false;
1405 Tree::RootListType::iterator j;
1406 for (j = mTree->GetDatabaseList().begin();
1407 j != mTree->GetDatabaseList().end();
1410 // std::cout << (*j)->GetName() << " "
1411 // << (*j)->GetTypeName()
1412 // << " i="<<(*j)->SupportsInsert()<<std::endl;
1413 if ( ((*j)!=itroot) && ((*j)->SupportsInsert()) )
1415 insertmenu->Append(PopUp_Insert+i,
1416 std2wx((*j)->GetName()));
1422 if (hasone) menu.AppendSubMenu(insertmenu, _T("&Insert into"));
1424 if (data->IsDatabase())
1426 menu.Append(PopUp_Close, wxT("&Close"));
1428 if (data->IsDicomNode() && data->GetDicomNode()->GetDicomDatabase()->SupportsRemove())
1430 menu.Append(PopUp_Remove, wxT("&Remove"));
1438 PopupMenu(&menu, pt);
1439 #endif // wxUSE_MENUS
1441 // std::cout << "EO ShowMenu" <<std::endl;
1443 //=====================================================================
1445 //=====================================================================
1446 // Pop up menu callbacks
1447 void WxGimmick::OnPopUpAbout(wxCommandEvent& event)
1449 wxMessageBox( _T("Give me my medical images quick ! \n\n (c) CREATIS-LRMN 2008\n laurent.guigues@creatis.insa-lyon.fr"),
1451 wxOK | wxICON_INFORMATION, this);
1453 //=====================================================================
1455 //=====================================================================
1456 void WxGimmick::OnPopUpSettings(wxCommandEvent& event)
1458 WxGimmickSettingsDialog* s =
1459 new WxGimmickSettingsDialog(this,&mSettings);
1463 //=====================================================================
1465 //=====================================================================
1466 void WxGimmick::OnPopUpNewCollection(wxCommandEvent& event)
1469 OpenOrNewDatabase(false);
1471 //=====================================================================
1475 //=====================================================================
1476 void WxGimmick::OnPopUpOpenCollection(wxCommandEvent& event)
1479 OpenOrNewDatabase(true);
1481 //=====================================================================
1484 //=====================================================================
1485 void WxGimmick::OnPopUpCloseCollection(wxCommandEvent& event)
1487 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;
1490 // std::cout << "OnPopUpClose"<<std::endl;
1491 // wxTreeItemId id = event.GetId();
1492 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1493 DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
1494 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1495 DeleteDicomDatabase(mItemOfMenu,r);
1497 //=====================================================================
1499 //=====================================================================
1500 void WxGimmick::OnPopUpDeleteCollection(wxCommandEvent& event)
1502 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;
1507 // std::cout << "OnPopUpClose"<<std::endl;
1508 // wxTreeItemId id = event.GetId();
1509 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1510 DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
1512 wxRemoveFile(std2wx(r->GetFileName()));
1513 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1514 DeleteDicomDatabase(mItemOfMenu,r);
1517 //=====================================================================
1519 void DisplayUpdateSummary( DicomDatabase::UpdateSummary& summary,
1522 std::stringstream mess;
1523 mess << "Dirs\tscanned\t\t\t: " << summary.scanned_dirs << "\n";
1524 mess << "Files\tscanned\t\t\t: " << summary.scanned_files << "\n";
1525 mess << "Files\thandled\t\t\t: " << summary.handled_images << "\n\n";
1526 mess << "Patients\tadded\t\t: " << summary.added_patients<< "\n";
1527 mess << "Studies\tadded\t\t: " << summary.added_studies<< "\n";
1528 mess << "Series\tadded\t\t: " << summary.added_series<< "\n";
1529 mess << "Images\tadded\t\t: " << summary.added_images<< "\n\n";
1531 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",
1533 (int)( summary.parse_time*100./summary.total_time),
1534 summary.file_scan_time,
1535 (int)(summary.file_scan_time*100./summary.total_time),
1536 summary.update_structs_time,
1537 (int)(summary.update_structs_time*100./summary.total_time),
1538 summary.update_database_time,
1539 (int)(summary.update_database_time*100./summary.total_time),
1540 summary.total_time );
1544 wxMessageBox(std2wx(mess.str()),_T("Update summary"),wxOK,parent);
1548 //=====================================================================
1549 void WxGimmick::OnPopUpAddFile(wxCommandEvent& event)
1551 long style = wxOPEN | wxFILE_MUST_EXIST | wxFD_MULTIPLE;
1552 std::string wc("*.*");
1553 wxFileDialog* FD = new wxFileDialog( 0,
1561 if (FD->ShowModal()==wxID_OK)
1565 mCurrentDirectory = FD->GetDirectory();
1566 wxArrayString files;
1567 FD->GetPaths(files);
1569 std::vector<std::string> filenames;
1570 for (i=0;i<files.GetCount();++i)
1571 filenames.push_back(wx2std(files[i]));
1574 TreeItemData *data =
1576 mTreeListCtrl->GetItemData(mItemOfMenu);
1577 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1578 DicomDatabase::UpdateSummary summary;
1579 wxProgressDialog* progress =
1580 new wxProgressDialog(_T("Adding file(s)"),
1585 wxPD_ESTIMATED_TIME |
1586 wxPD_REMAINING_TIME |
1589 db->AddFiles(filenames,progress,summary);
1591 progress->Pulse(_T("Updating view..."));
1592 UpdateDicomDatabaseView(db);
1594 DisplayUpdateSummary(summary,this);
1598 //=====================================================================
1600 //=====================================================================
1601 void WxGimmick::OnPopUpAddRawFile(wxCommandEvent& event)
1603 wxMessageBox(_T("Not yet implemented !"),_T("Sorry"),wxOK,this);
1605 //=====================================================================
1607 //=====================================================================
1608 void WxGimmick::OnPopUpAddDirectory(wxCommandEvent& event)
1610 long style = wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST;
1613 _T("Select directory"),
1617 if (FD->ShowModal()==wxID_OK)
1620 bool recurse = false;
1621 if (wxMessageBox(_T("Recurse into sub-directories ?"),
1622 _T("Scan directory"),
1623 wxYES_NO,this ) == wxYES)
1629 wxProgressDialog* progress =
1630 new wxProgressDialog(_T("Scanning directory"),
1631 _T("Parsing directory"),
1635 wxPD_ESTIMATED_TIME |
1636 wxPD_REMAINING_TIME |
1638 DicomDatabase::UpdateSummary summary;
1640 std::string dirname = wx2std (FD->GetPath()) ;
1641 mCurrentDirectory = FD->GetPath();
1642 TreeItemData *data =
1644 mTreeListCtrl->GetItemData(mItemOfMenu);
1645 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1646 db->AddDirectory(dirname,recurse,progress,summary);
1648 progress->Pulse(_T("Updating view..."));
1649 UpdateDicomDatabaseView(db);
1652 DisplayUpdateSummary(summary,this);
1654 if (summary.cancelled_by_user)
1656 std::cout << "!! Cancelled by user !!"<<std::endl;
1662 //=====================================================================
1664 //=====================================================================
1665 void WxGimmick::OnPopUpRemove(wxCommandEvent& event)
1669 wxMessageBox(_T("Not yet implemented"),_T("Sorry !"),wxOK);
1673 // wxTreeItemId id = event.GetId();
1674 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1676 std::string mess("Remove ");
1677 mess += data->GetDicomNode()->GetTypeName();
1678 mess += " from collection ?";
1679 int answer = wxMessageBox(std2wx(mess), _T("Confirm"), wxYES_NO);
1680 if (answer == wxNO) return;
1682 if ( mTreeListCtrl->IsSelected(mItemOfMenu) )
1684 wxTreeItemId next = mTreeListCtrl->GetNextSibling(mItemOfMenu);
1687 mTreeListCtrl->SelectItem(next);
1695 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1696 db->Remove(data->GetDicomNode());
1697 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1698 // TODO : Optimize update only parent's branch
1699 UpdateDicomDatabaseView(db);
1700 // DeleteDicomDatabase(mItemOfMenu,r);
1702 //=====================================================================
1704 //=====================================================================
1705 void WxGimmick::OnPopUpSort(wxCommandEvent& event)
1708 // std::cout << "OnPopUpSort"<<std::endl;
1709 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1710 int index = event.GetId() - PopUp_Sort;
1711 DicomNode* node = data->GetDicomNode();
1712 DicomNode::Type ctype = node->GetType()+1;
1713 mSettings.SetActiveComparatorIndex(ctype,index);
1715 if (node->ChildrenLoaded())
1718 mTreeListCtrl->DeleteChildren(mItemOfMenu);
1720 /* std::cout << "Sorting using '"
1721 << mSettings.GetActiveComparator(ctype).GetName()
1724 node->SortChildren ( mSettings.GetActiveComparator(ctype) );
1725 // std::cout << "ok"<<std::endl;
1729 CreateChildrenColumnsTitles(mItemOfMenu,ctype);
1730 DicomNode::ChildrenListType::iterator i;
1731 for (i=node->GetChildrenList().begin();
1732 i!=node->GetChildrenList().end();
1735 UpdateDicomNodeView(*i,mItemOfMenu);
1739 //=====================================================================
1742 //=====================================================================
1743 void WxGimmick::OnPopUpUser(wxCommandEvent& event)
1745 // std::cout << "OnPopUpUser"<<std::endl;
1748 //=====================================================================
1750 //=================================================
1751 void WxGimmick::CreateImageList(int size)
1755 mTreeListCtrl->SetImageList(NULL);
1764 // should correspond to Icon_xxx enum
1765 icons[Icon_Patient] = wxIcon(patient_xpm);
1766 icons[Icon_Study] = wxIcon(study_xpm);
1767 icons[Icon_Series] = wxIcon(series_xpm);
1768 icons[Icon_Image] = wxIcon(image_xpm);
1769 icons[Icon_Database] = wxIcon(database_xpm);
1770 icons[Icon_Folder] = wxIcon(folder_xpm);
1771 icons[Icon_DicomDir] = wxIcon(dicomdir_xpm);
1772 icons[Icon_Root] = wxIcon(root_xpm);
1775 // mFirstRootIconIndex = 8;
1778 Tree::RootHandlerListType::iterator h;
1780 for (h= Tree::GetDatabaseHandlerList().begin();
1781 h!=Tree::GetDatabaseHandlerList().end();
1784 icons[mFirstRootIconIndex+i] = (*h)->GetIcon();
1788 unsigned int NbIcons = 8;//mFirstRootIconIndex + i;
1789 // Make an image list containing small icons
1790 wxImageList *images = new wxImageList(size, size, true);
1792 int sizeOrig = icons[0].GetWidth();
1793 for ( size_t i = 0; i < NbIcons; i++ )
1795 if ( size == sizeOrig )
1797 images->Add(icons[i]);
1801 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
1804 mTreeListCtrl->AssignImageList(images);
1806 //=================================================
1815 //================================================================
1816 bool WxGimmick::IsImageSelectable(DicomNode* node)
1818 int rows = node->ImageGetRows();
1819 int cols = node->ImageGetColumns();
1820 int frms = node->ImageGetFrames();
1822 // std::cout << "R/C/F = " << rows << "/"<< cols <<"/"<<frms<<std::endl;
1826 else if (cols>0) dim=2;
1827 else if (rows>0) dim=1;
1831 std::cout << "Unknown image dimension : cannot select !"
1835 else if (dim>mSelectionMaxImageDimension)
1837 std::cout << "Selecting "<<dim<<"D images is not allowed !"
1842 if ( mTreeListCtrl->GetSelectionSize() == 0 )
1844 mCurrentSelectionImageSize[0] = cols;
1845 mCurrentSelectionImageSize[1] = rows;
1846 mCurrentSelectionImageSize[2] = frms;
1851 if ( dim == mSelectionMaxImageDimension )
1853 std::cout << "Cannot add this image to selection : would result in a "<<dim+1<<"D image !" << std::endl;
1856 if ( ( cols != mCurrentSelectionImageSize[0] ) ||
1857 ( rows != mCurrentSelectionImageSize[1] ) ||
1858 ( frms != mCurrentSelectionImageSize[2] ) )
1860 std::cout << "Cannot add this image to selection : image size is incomptatible with currently selected images" << std::endl;
1864 // std::cout << "Selecting : "<<node->ImageGetFullFileName() << std::endl;
1867 //================================================================
1869 //================================================================
1870 void WxGimmick::OnSelChanging(wxTreeEvent& event)
1873 wxTreeItemId id = event.GetItem();
1876 std::cout << "INTERNAL ERROR : ID NOT OK"<<std::endl;
1881 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1882 if (data->IsDicomNode())
1884 if (data->GetDicomNode()>0)
1886 // An image was selected
1887 if (data->GetDicomNode()->GetType()==DicomNode::Image)
1889 if (IsImageSelectable(data->GetDicomNode())) event.Allow();
1891 // A series was selected
1892 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
1894 // If images not loaded do it
1896 // can be selected if all its images can
1898 wxTreeItemIdValue cookie;
1899 for (child = mTreeListCtrl->GetFirstChild(id,cookie);
1901 child = mTreeListCtrl->GetNextChild(id,cookie))
1903 TreeItemData *cdata =
1904 (TreeItemData *)mTreeListCtrl->GetItemData(child);
1905 if ((cdata->IsDicomNode())&&
1906 (cdata->GetDicomNode()>0)&&
1907 (cdata->GetDicomNode()->GetType()==DicomNode::Image)&&
1908 (!IsImageSelectable(cdata->GetDicomNode())))
1916 //================================================================
1918 //================================================================
1919 void WxGimmick::OnSelChanged(wxTreeEvent& event)
1921 // wxBusyCursor busy;
1922 // std::vector<wxTreeItemId> items;
1923 // GetSelectedItems(items);
1925 std::vector<DicomNode*>::iterator i;
1926 for (i=nodes.begin();i!=nodes.end();++i)
1928 std::cout << "'" << (*i)->GetFieldValue("FullFileName")
1929 << "'" << std::endl;
1931 std::cout << "++++++++++++++++++++" << std::endl;
1933 // ShowImage(mReader.GetImage(""));
1935 bool no_image = true;
1937 static int max = 1000;
1940 // if (items.size()>0)
1943 // Update image preview : send requests to the MTImageReader
1944 // bool first = true;
1945 // std::vector<wxTreeItemId>::iterator i;
1946 // for (i=items.begin();i!=items.end();++i)
1952 DicomNode* node = GetDicomNodeOfItem(items[0]);
1954 // Update dicom fields panel
1955 mFieldsView->UpdateValues(node);
1959 wxTreeItemId item = mTreeListCtrl->GetCurrent();
1961 DicomNode* n = GetDicomNodeOfItem(item);
1963 if (n) mFieldsView->UpdateValues(n);
1966 (n->GetType()==DicomNode::Image) )
1971 //if (i==items.begin())
1972 mCurImageItemToShow = item;
1974 int maxprio = mReader.GetMaximalPriority();
1975 int prio = maxprio + 1000;
1976 wxTreeItemId sib = item; //GetTreeListCtrl()->GetNextSibling(*i);
1979 DicomNode* nsib = GetDicomNodeOfItem(sib);
1982 // std::cout << "-- Request '"
1983 // << nsib->GetFieldValue("FullFileName")
1984 // << "' prio="<<prio<<std::endl;
1985 mReader.Request(this,
1986 nsib->ImageGetFullFileName(),
1988 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
1992 sib = GetTreeListCtrl()->GetNextSibling(sib);
1994 prio = maxprio + 1000;
1995 sib = GetTreeListCtrl()->GetPrevSibling(item);
1998 DicomNode* nsib = GetDicomNodeOfItem(sib);
2001 // std::cout << "-- Request '"
2002 // << nsib->GetFieldValue("FullFileName")
2003 // << "' prio="<<prio<<std::endl;
2004 mReader.Request(this,
2005 nsib->ImageGetFullFileName(),
2007 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
2011 sib = GetTreeListCtrl()->GetPrevSibling(sib);
2013 // mImageFileNameToNode[n->GetFieldValue("FullFileName")] = n;
2016 ProcessImageEvents();
2018 // std::cout << "* Selection changed * (im)"<<std::endl;
2020 //---------------------------------------------------------------------
2022 WxGimmickEvent ev(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED,
2026 GetEventHandler()->ProcessEvent(ev);
2028 if (no_image) ShowImage(mReader.GetImage(""));
2031 //================================================================
2033 //================================================================
2034 void WxGimmick::ShowImage(vtkImageData* im)
2036 // wxBusyCursor busy;
2038 int x1,x2,y1,y2,z1,z2;
2040 im->GetSpacing(spx,spy,spz);
2041 im->GetExtent (x1,x2,y1,y2,z1,z2);
2044 std::cout << x1 << "-"<<x2<<std::endl;
2045 std::cout << y1 << "-"<<y2<<std::endl;
2046 std::cout << z1 << "-"<<z2<<std::endl;
2047 std::cout << spx << "-"<<spy<<"-"<<spz<<std::endl;
2071 vtkCamera *camera = mViewer->GetRenderer()->GetActiveCamera();
2073 camera->SetViewUp ( spx*0, -spy*1, spz*0);
2074 camera->SetPosition( spx*(x1+x2)/2, spy*(y1+y2)/2, -spz*10000000);
2075 camera->SetFocalPoint ( spx*(x1+x2)/2 , spy*(y1+y2)/2 , spz*0);
2077 camera->ComputeViewPlaneNormal();
2078 camera->SetParallelScale( spx*(x2-x1)/2.0 );
2082 mViewer->SetInput( im );
2083 mViewer->SetSlice( 0 );
2084 mInteractor->Render();
2086 //================================================================
2093 //================================================================
2095 OnMultiThreadImageReaderEvent(const std::string& filename,
2096 MultiThreadImageReaderUser::EventType e,
2097 vtkImageData* image)
2099 if (filename.size()==0)
2101 mImageEventQueue.push_back(ImageEventType(image));
2104 std::map<std::string,DicomNode*>::iterator i;
2105 i = mImageFileNameToNode.find(filename);
2106 if (i!=mImageFileNameToNode.end())
2108 wxTreeItemId id = i->second->GetData<NodeData*>()->GetTreeItemData()->GetItemId();
2109 mImageEventQueue.push_back(ImageEventType(id,image));
2112 //================================================================
2114 //================================================================
2115 // Processes the queue of image events
2116 void WxGimmick::ProcessImageEvents()
2118 // std::cout << "++++++++++ ProcessImageEvents " << std::endl;
2119 MultiThreadImageReaderEventLock();
2122 while (!mImageEventQueue.empty())
2124 ImageEventType e = mImageEventQueue.front();
2125 mImageEventQueue.pop_front();
2130 mTreeListCtrl->SetItemTextColour(e.item,
2131 mSettings.LoadedImageColour());//wxImageLoadedColour);
2132 TreeItemData *data =
2133 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2134 data->SetLoaded(true);
2136 if (mCurImageItemToShow == e.item)
2141 else if (!mCurImageItemToShow.IsOk())
2146 else if (e.item.IsOk())
2148 mTreeListCtrl->SetItemTextColour(e.item,mSettings.Colour(DicomNode::Image)); //.wxImageUnloadedColour);
2149 TreeItemData *data =
2150 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2151 data->SetLoaded(false);
2154 mImageEventQueue.clear();
2155 MultiThreadImageReaderEventUnlock();
2156 // std::cout << "++++++++++ END ProcessImageEvents " << std::endl;
2158 //================================================================
2160 //================================================================
2161 void WxGimmick::OnInternalIdle()
2163 ProcessImageEvents();
2168 mJustStarted = false;
2173 //================================================================
2176 //================================================================
2177 // LG : For the moment any selection is valid but in the future
2178 // incomplete selections can be invalid...
2179 bool WxGimmick::IsSelectionValid()
2181 return (mTreeListCtrl->GetSelectionSize()>0);
2183 //================================================================
2185 //================================================================
2186 void WxGimmick::GetSelectedFiles(std::vector<std::string>& f)
2188 wxArrayTreeItemIds id;
2189 // TO DO : TEST THAT STYLE IS MULTIPLE
2190 unsigned int nb = mTreeListCtrl->GetSelections(id);
2192 for (unsigned int i=0; i<nb; ++i)
2194 TreeItemData *data =
2195 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2196 if ((data) && (data->IsDicomNode()))
2198 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2200 f.push_back ( data->GetDicomNode()->ImageGetFullFileName() );
2202 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2204 DicomNode::ChildrenListType::iterator j;
2205 for (j =data->GetDicomNode()->GetChildrenList().begin();
2206 j!=data->GetDicomNode()->GetChildrenList().end();
2209 f.push_back((*j)->ImageGetFullFileName());
2215 //================================================================
2217 //================================================================
2218 void WxGimmick::GetSelectedImages(std::vector<vtkImageData*>& f)
2220 wxArrayTreeItemIds id;
2221 // TO DO : TEST THAT STYLE IS MULTIPLE
2222 unsigned int nb = mTreeListCtrl->GetSelections(id);
2225 // Collect the brute vector of Image nodes
2226 std::vector<DicomNode*> im;
2227 for (unsigned int i=0; i<nb; ++i)
2229 TreeItemData *data =
2230 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2231 if ((data) && (data->IsDicomNode()))
2233 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2235 im.push_back ( data->GetDicomNode() );
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 im.push_back ( *j );
2250 // Create the output data
2253 // Only one image : give it
2254 vtkImageData* out = vtkImageData::New();
2255 out->ShallowCopy(mReader.GetImage(im.front()->ImageGetFullFileName()));
2258 else if (im.size()>1)
2260 vtkImageData* first = mReader.GetImage( im.front()->ImageGetFullFileName() );
2261 if (first->GetDataDimension()==2)
2264 vtkImageData* out = vtkImageData::New();
2265 out->CopyStructure(first);
2266 out->SetScalarType(first->GetScalarType());
2268 first->GetExtent(ext);
2270 out->SetExtent(ext);
2271 // LG : TODO : Z Spacing ?
2273 out->AllocateScalars();
2275 //first->Print(std::cout);
2276 // out->Print(std::cout);
2279 first->GetDimensions(dim);
2280 unsigned long imsize =
2281 ( (unsigned long)first->GetScalarPointer(0,1,0)
2282 - (unsigned long)first->GetScalarPointer(0,0,0))
2286 std::vector<DicomNode*>::iterator it;
2287 for (it=im.begin(); it!=im.end(); ++it)
2289 //std::cout << "copying slice "<<slice <<std::endl;
2290 vtkImageData* cur = mReader.GetImage( (*it)->ImageGetFullFileName() );
2292 void* src = cur->GetScalarPointer(0,0,0);
2293 void* dst = out->GetScalarPointer(0,0,slice);
2294 // std::cout << "src="<<src<<std::endl;
2295 // std::cout << "dst="<<dst<<std::endl;
2296 // std::cout << "siz="<<imsize<<std::endl;
2297 memcpy(dst,src,imsize);
2302 for (ii=1;ii<4;ii++) {
2303 for (jj=1;jj<4;jj++) {
2304 int x = (int)(ii*dim[0] / 4);
2305 int y = (int)(jj*dim[1] / 4);
2306 std::cout << cur->GetScalarComponentAsFloat(x,y,0,0)
2308 << out->GetScalarComponentAsFloat(x,y,slice,0)
2321 std::vector<DicomNode*>::iterator it;
2322 for (it=im.begin(); it!=im.end(); ++it)
2324 vtkImageData* out = vtkImageData::New();
2325 out->ShallowCopy(mReader.GetImage((*it)->ImageGetFullFileName()));
2331 //================================================================
2334 //================================================================
2335 void WxGimmick::GetSelectedDicomNodes(std::vector<DicomNode*>& f)
2337 wxArrayTreeItemIds id;
2338 // TO DO : TEST THAT STYLE IS MULTIPLE
2339 unsigned int nb = mTreeListCtrl->GetSelections(id);
2341 for (unsigned int i=0; i<nb; ++i)
2343 TreeItemData *data =
2344 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2345 if ((data) && (data->IsDicomNode()))
2347 f.push_back ( data->GetDicomNode() );
2351 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2353 f.push_back ( data->GetDicomNode() ); //->ImageGetFullFileName() );
2355 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2357 DicomNode::ChildrenListType::iterator j;
2358 for (j =data->GetDicomNode()->GetChildrenList().begin();
2359 j!=data->GetDicomNode()->GetChildrenList().end();
2362 f.push_back((*j)); //->ImageGetFullFileName() ); }
2368 //================================================================
2370 //================================================================
2371 void WxGimmick::GetSelectedItems(std::vector<wxTreeItemId>& 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)
2382 //================================================================
2384 //================================================================
2385 DicomNode* WxGimmick::GetDicomNodeOfItem(const wxTreeItemId& i)
2387 TreeItemData *data =
2388 (TreeItemData *)mTreeListCtrl->GetItemData(i);
2389 if (data) return ( data->GetDicomNode() );
2392 //================================================================
2394 //================================================================
2395 //================================================================
2396 //================================================================
2397 //================================================================
2413 //================================================================
2414 //================================================================
2415 //================================================================
2416 //================================================================
2418 BEGIN_EVENT_TABLE(WxGimmick, wxPanel)
2420 EVT_MENU(PopUp_NewCollection,WxGimmick::OnPopUpNewCollection)
2421 EVT_MENU(PopUp_OpenCollection,WxGimmick::OnPopUpOpenCollection)
2422 EVT_MENU(PopUp_CloseCollection,WxGimmick::OnPopUpCloseCollection)
2423 EVT_MENU(PopUp_DeleteCollection,WxGimmick::OnPopUpDeleteCollection)
2424 EVT_MENU(PopUp_AddFile, WxGimmick::OnPopUpAddFile)
2425 EVT_MENU(PopUp_AddRawFile, WxGimmick::OnPopUpAddRawFile)
2426 EVT_MENU(PopUp_AddDirectory, WxGimmick::OnPopUpAddDirectory)
2427 EVT_MENU(PopUp_Remove, WxGimmick::OnPopUpRemove)
2428 EVT_MENU(PopUp_About, WxGimmick::OnPopUpAbout)
2429 EVT_MENU(PopUp_Settings, WxGimmick::OnPopUpSettings)
2431 EVT_MENU_RANGE(PopUp_Sort, PopUp_Sort+99, WxGimmick::OnPopUpSort)
2432 EVT_MENU_RANGE(PopUp_User, PopUp_User+99, WxGimmick::OnPopUpUser)
2437 EVT_TREE_BEGIN_DRAG(TreeListCtrlId, WxGimmick::OnBeginDrag)
2438 EVT_TREE_BEGIN_RDRAG(TreeListCtrlId, WxGimmick::OnBeginRDrag)
2439 EVT_TREE_END_DRAG(TreeListCtrlId, WxGimmick::OnEndDrag)
2442 EVT_TREE_BEGIN_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnBeginLabelEdit)
2443 EVT_TREE_END_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnEndLabelEdit)
2446 EVT_TREE_DELETE_ITEM(TreeListCtrlId, WxGimmick::OnDeleteItem)
2447 #if 0 // there are so many of those that logging them causes flicker
2448 EVT_TREE_GET_INFO(TreeListCtrlId, WxGimmick::OnGetInfo)
2451 EVT_TREE_SET_INFO(TreeListCtrlId, WxGimmick::OnSetInfo)
2454 EVT_TREE_ITEM_EXPANDED(TreeListCtrlId, WxGimmick::OnItemExpanded)
2455 EVT_TREE_ITEM_EXPANDING(TreeListCtrlId, WxGimmick::OnItemExpanding)
2456 EVT_TREE_ITEM_COLLAPSED(TreeListCtrlId, WxGimmick::OnItemCollapsed)
2457 EVT_TREE_ITEM_COLLAPSING(TreeListCtrlId, WxGimmick::OnItemCollapsing)
2460 EVT_TREE_SEL_CHANGED(TreeListCtrlId, WxGimmick::OnSelChanged)
2461 EVT_TREE_SEL_CHANGING(TreeListCtrlId, WxGimmick::OnSelChanging)
2463 EVT_TREE_KEY_DOWN(TreeListCtrlId, WxGimmick::OnTreeKeyDown)
2464 // ACTIVATION = DOUBLE CLICK OR ENTER ON SELECTED
2465 EVT_TREE_ITEM_ACTIVATED(TreeListCtrlId, WxGimmick::OnItemActivated)
2467 // so many differents ways to handle right mouse button clicks...
2468 // EVT_CONTEXT_MENU(WxGimmick::OnContextMenu)
2469 // EVT_TREE_ITEM_MENU is the preferred event for creating context menus
2470 // on a tree control, because it includes the point of the click or item,
2471 // meaning that no additional placement calculations are required.
2472 // EVT_TREE_ITEM_MENU(TreeListCtrlId, WxGimmick::OnItemMenu)
2474 EVT_TREE_ITEM_RIGHT_CLICK(TreeListCtrlId, WxGimmick::OnItemRightClick)
2477 // EVT_RIGHT_DOWN(WxGimmick::OnRMouseDown)
2478 // EVT_RIGHT_UP(WxGimmick::OnRMouseUp)
2479 // EVT_RIGHT_DCLICK(WxGimmick::OnRMouseDClick)
2482 //IMPLEMENT_DYNAMIC_CLASS(WxGimmick, wxTreeListCtrl)
2485 wxTree::wxTree(wxWindow *parent, const wxWindowID id,
2486 const wxPoint& pos, const wxSize& size,
2488 : wxTreeListCtrl(parent, id, pos, size, style)
2490 m_reverseSort = false;
2494 // Add some items to the tree
2495 AddTestItemsToTree(5, 2);
2501 #if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
2502 void WxGimmick::CreateButtonsImageList(int size)
2507 mTreeListCtrl->SetButtonsImageList(NULL);
2511 // Make an image list containing small icons
2512 wxImageList *images = new wxImageList(size, size, true);
2514 // should correspond to TreeListCtrlIcon_xxx enum
2517 icons[0] = wxIcon(icon3_xpm); // closed
2518 icons[1] = wxIcon(icon3_xpm); // closed, selected
2519 icons[2] = wxIcon(icon5_xpm); // open
2520 icons[3] = wxIcon(icon5_xpm); // open, selected
2522 for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
2524 int sizeOrig = icons[i].GetWidth();
2525 if ( size == sizeOrig )
2527 images->Add(icons[i]);
2531 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
2535 mTreeListCtrl->AssignButtonsImageList(images);
2538 void WxGimmick::CreateButtonsImageList(int WXUNUSED(size))
2544 int WxGimmick::OnCompareItems(const wxTreeItemId& item1,
2545 const wxTreeItemId& item2)
2547 if ( m_reverseSort )
2549 // just exchange 1st and 2nd items
2550 return mTreeListCtrl->OnCompareItems(item2, item1);
2554 return mTreeListCtrl->OnCompareItems(item1, item2);
2559 void WxGimmick::DoToggleIcon(const wxTreeItemId& item)
2562 int image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_Folder)
2565 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Normal);
2567 image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_FolderSelected)
2568 ? TreeIcon_FileSelected
2569 : TreeIcon_FolderSelected;
2570 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Selected);
2573 void WxGimmick::LogEvent(const wxChar *name, const wxTreeEvent& event)
2575 wxTreeItemId item = event.GetItem();
2578 text << _T('"') << mTreeListCtrl->GetItemText(item).c_str() << _T('"');
2580 text = _T("invalid item");
2581 // wxLogMessage(wxT("%s(%s)"), name, text.c_str());
2586 #define TREE_EVENT_HANDLER(name) \
2587 void WxGimmick::name(wxTreeEvent& event) \
2589 /* LogEvent(_T(#name), event); */ \
2590 /* SetLastItem(mTreeListCtrl->wxTreeItemId()) *;*/ \
2594 TREE_EVENT_HANDLER(OnBeginRDrag)
2595 TREE_EVENT_HANDLER(OnDeleteItem)
2596 TREE_EVENT_HANDLER(OnGetInfo)
2597 TREE_EVENT_HANDLER(OnSetInfo)
2598 //TREE_EVENT_HANDLER(OnItemExpanded)
2599 TREE_EVENT_HANDLER(OnItemExpanding)
2600 //TREE_EVENT_HANDLER(OnItemCollapsed)
2601 //TREE_EVENT_HANDLER(OnSelChanged)
2602 // TREE_EVENT_HANDLER(OnSelChanging)
2605 void WxGimmick::OnItemCollapsed(wxTreeEvent& event)
2607 // std::cout << "* Collapsed *"<<std::endl;
2610 #undef TREE_EVENT_HANDLER
2612 void WxGimmick::OnTreeKeyDown(wxTreeEvent& event)
2615 // LogKeyEvent(wxT("Tree key down "), event.GetKeyEvent());
2616 std::cout << "* Key down *"<<std::endl;
2617 if (event.GetKeyCode()==WXK_RIGHT)
2619 std::cout << "Right"<<std::endl;
2620 wxTreeItemId itemId = mTreeListCtrl->GetSelection();
2623 std::cout << "item is ok"<<std::endl;
2624 wxPoint clientpt = event.GetPoint();
2625 wxPoint screenpt = ClientToScreen(clientpt);
2626 ShowMenu(itemId, clientpt);
2631 std::cout << "NOT Right"<<std::endl;
2636 void WxGimmick::OnBeginDrag(wxTreeEvent& event)
2638 wxTreeItemId id = event.GetItem();
2639 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2640 // std::cout << "OnBeginDrag("<<id<<")"<<std::endl;
2641 if (data->IsDatabase())
2643 // std::cout << "-- IS ROOT"<<std::endl;
2646 else if (data->IsDicomNode())
2648 // std::cout << "-- IS NODE"<<std::endl;
2651 // need to explicitly allow drag
2652 if ( event.GetItem() != GetDatabaseItem() )
2654 m_draggedItem = event.GetItem();
2656 wxPoint clientpt = event.GetPoint();
2657 wxPoint screenpt = ClientToScreen(clientpt);
2659 wxLogMessage(wxT("OnBeginDrag: started dragging %s at screen coords (%i,%i)"),
2660 GetItemText(m_draggedItem).c_str(),
2661 screenpt.x, screenpt.y);
2667 wxLogMessage(wxT("OnBeginDrag: this item can't be dragged."));
2672 void WxGimmick::OnEndDrag(wxTreeEvent& event)
2674 wxTreeItemId id = event.GetItem();
2675 // std::cout << "OnEndDrag("<<id<<")"<<std::endl;
2676 if (!id.IsOk()) return;
2677 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2678 if (data->IsDatabase())
2680 // std::cout << "-- IS ROOT"<<std::endl;
2682 else if (data->IsDicomNode())
2684 // std::cout << "-- IS NODE"<<std::endl;
2688 wxTreeItemId itemSrc = m_draggedItem,
2689 itemDst = event.GetItem();
2690 m_draggedItem = (wxTreeItemId)0l;
2692 // where to copy the item?
2693 if ( itemDst.IsOk() && !ItemHasChildren(itemDst) )
2695 // copy to the parent then
2696 itemDst = GetItemParent(itemDst);
2699 if ( !itemDst.IsOk() )
2701 wxLogMessage(wxT("OnEndDrag: can't drop here."));
2706 wxString text = GetItemText(itemSrc);
2707 wxLogMessage(wxT("OnEndDrag: '%s' copied to '%s'."),
2708 text.c_str(), GetItemText(itemDst).c_str());
2710 // just do append here - we could also insert it just before/after the item
2711 // on which it was dropped, but this requires slightly more work... we also
2712 // completely ignore the client data and icon of the old item but could
2713 // copy them as well.
2715 // Finally, we only copy one item here but we might copy the entire tree if
2716 // we were dragging a folder.
2717 int image = wxGetApp().ShowImages() ? TreeIcon_File : -1;
2718 AppendItem(itemDst, text, image);
2723 //====================================================================
2724 void WxGimmick::OnBeginLabelEdit(wxTreeEvent& event)
2726 // std::cout << "OnBeginLabelEdit"<<std::endl;
2727 wxTreeItemId id = event.GetItem();
2728 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2729 // If not a root : veto
2730 if (data->IsDatabase())
2737 //====================================================================
2739 //====================================================================
2740 void WxGimmick::OnEndLabelEdit(wxTreeEvent& event)
2742 // std::cout << "OnEndLabelEdit"<<std::endl;
2743 wxTreeItemId id = event.GetItem();
2744 TreeItemData *data = GetItemData(id);
2745 // If not a database : bug !
2746 if (data->IsDatabase())
2748 data->GetDicomNode()->GetDicomDatabase()->SetName(wx2std(event.GetLabel()));
2749 mFieldsView->UpdateValues(data->GetDicomNode());
2753 std::cerr<< "!!!! Internal error : send bug report !!!!"<<std::endl;
2756 //====================================================================
2759 void WxGimmick::OnItemCollapsing(wxTreeEvent& event)
2761 // wxLogMessage(wxT("OnItemCollapsing"));
2763 // for testing, prevent the user from collapsing the first child folder
2764 wxTreeItemId itemId = event.GetItem();
2767 if ( IsTestItem(itemId) )
2769 wxMessageBox(wxT("You can't collapse this item."));
2777 //====================================================================
2778 void WxGimmick::ShowHelp()
2783 mHelpWindow = new WxGimmickHelpWindow(this);
2785 mHelpWindow->CenterOnParent();
2786 mHelpWindow->ShowModal();
2789 //====================================================================
2795 //================================================================
2796 //================================================================
2797 //================================================================
2798 //================================================================
2799 //================================================================
2801 //================================================================
2802 //================================================================
2803 //================================================================
2804 //================================================================
2805 //================================================================
2811 // ----------------------------------------------------------------------------
2813 // ----------------------------------------------------------------------------
2815 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_DRAG)
2816 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_RDRAG)
2817 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_DELETE_ITEM)
2818 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_GET_INFO)
2819 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SET_INFO)
2820 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDED)
2821 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDING)
2822 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSED)
2823 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSING)
2826 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT)
2827 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_LABEL_EDIT)
2830 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED)
2831 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGING)
2832 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_KEY_DOWN)
2833 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU)
2834 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_ITEM_STYLE_CHANGED)
2836 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_ACTIVATED)
2837 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK)
2838 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK)
2839 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_DRAG)
2840 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK)
2841 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP)
2842 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MENU)
2844 // ----------------------------------------------------------------------------
2846 // ----------------------------------------------------------------------------
2848 IMPLEMENT_ABSTRACT_CLASS(WxGimmickEvent, wxNotifyEvent)
2851 WxGimmickEvent::WxGimmickEvent(wxEventType commandType,
2853 const wxTreeItemId& item)
2855 wxNotifyEvent(commandType, tree->GetId()),
2859 // m_editCancelled = false;
2861 SetEventObject(tree);
2864 SetClientObject(tree->mTreeListCtrl->GetItemData(item));
2867 WxGimmickEvent::WxGimmickEvent(wxEventType commandType, int id)
2869 wxNotifyEvent(commandType, id),
2873 // m_editCancelled = false;
2876 WxGimmickEvent::WxGimmickEvent(const WxGimmickEvent & event)
2878 wxNotifyEvent(event),
2882 m_evtKey = event.m_evtKey;
2883 m_item = event.m_item;
2884 m_itemOld = event.m_itemOld;
2885 mColor = event.mColor;
2886 mUserData = event.mUserData;
2887 // m_pointDrag = event.m_pointDrag;
2888 // m_label = event.m_label;
2889 // m_editCancelled = event.m_editCancelled;
2899 //================================================================
2900 //================================================================
2901 //================================================================
2902 //================================================================
2903 //================================================================
2904 WxGimmickFrame::WxGimmickFrame( wxWindow *parent,
2907 : wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size)
2909 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
2910 mWxGimmick = new WxGimmick(this,-1,
2913 sizer->Add(mWxGimmick,1,wxGROW);
2915 SetAutoLayout(true);
2918 //================================================================
2920 //================================================================
2921 WxGimmickFrame::~WxGimmickFrame()
2924 //================================================================
2926 //================================================================
2927 void WxGimmickFrame::OnSelChanged(WxGimmickEvent& event)
2929 // std::cout << "+++++ WxGimmickFrame::OnSelChanged ++++++++++"
2931 std::vector<std::string> file;
2932 // mWxGimmick->GetSelectedImages(file);
2934 std::vector<std::string>::iterator i;
2935 for (i=file.begin();i!=file.end();++i)
2937 std::cout << "'" << *i << "'" << std::endl;
2939 std::cout << "++++++++++++++++++++" << std::endl;
2942 //================================================================
2944 //================================================================
2945 BEGIN_EVENT_TABLE(WxGimmickFrame, wxFrame)
2946 EVT_TREEVIEWLIST_SEL_CHANGED(-1,WxGimmickFrame::OnSelChanged)
2948 //================================================================