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;
936 creaMessage("Gimmick!",1,"Gimmick! : ==> Loading collections from '"<<mDatabaseListFile<<"'"<<std::endl);
940 s.open(mDatabaseListFile.c_str());
947 if (str.size()==0) continue;
949 std::vector<std::string> tokens;
950 boost::split( tokens, str, boost::is_any_of("\t") );
952 DicomDatabase* db = new DicomDatabase(tokens[0]);
954 // std::cout << " -> Loading collection '"<<tokens[0]<<"'"<<std::endl;
956 if (tokens.size()==2)
958 db->SetName(tokens[1]);
963 GetDicomDatabaseList().push_back(db);
964 db->DBLoadChildren(db,DicomNode::Patient);
965 if (mSettings.HasActiveComparator(DicomNode::Patient))
968 ( mSettings.GetActiveComparator(DicomNode::Patient) );
973 creaMessage("Gimmick!",1," ==> ERROR opening collection '"<<tokens[0]<<"'"<<std::endl);
981 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).");
985 mTreeListCtrl->SetBackgroundColour(mSettings.BgColour(DicomNode::Database));
986 if (GetDicomDatabaseList().begin() !=
987 GetDicomDatabaseList().end() )
989 mFieldsView->UpdateFields(*GetDicomDatabaseList().begin());
995 //================================================================
997 //================================================================
998 void WxGimmick::SaveConfiguration()
1001 creaMessage("Gimmick!",1,"Gimmick! : Saving configuration..."<<std::endl);
1003 creaMessage("Gimmick!",1,"Gimmick! : ==> Saving collections in '"
1004 <<mDatabaseListFile<<"'"<<std::endl);
1007 s.open(mDatabaseListFile.c_str());
1010 creaError("Gimmick! : error opening '"<<mDatabaseListFile<<"'");
1013 DicomDatabaseListType::iterator i;
1014 for (i =GetDicomDatabaseList().begin();
1015 i!=GetDicomDatabaseList().end();
1018 s << (*i)->GetFileName() << "\t";
1019 s << (*i)->GetName() << std::endl;
1025 //================================================================
1028 //================================================================
1029 void WxGimmick::OnClose(wxCloseEvent& event)
1031 if (mSaveConfigurationOnClose) SaveConfiguration();
1033 //================================================================
1035 //================================================================
1036 void WxGimmick::OnItemActivated(wxTreeEvent& event)
1042 // std::cout << "OnItemActivated" <<std::endl;
1043 wxTreeItemId itemId = event.GetItem();
1044 if (mTreeListCtrl->IsExpanded(itemId))
1046 mTreeListCtrl->Collapse(itemId);
1050 mTreeListCtrl->Expand(itemId);
1053 //================================================================
1055 //================================================================
1056 void WxGimmick::LoadChildren(wxTreeItemId& id)
1058 TreeItemData *item = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1061 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1062 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1065 // If children not already loaded : do it
1067 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1068 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1071 // Some new children loaded
1073 if (mSettings.HasActiveComparator
1074 (item->GetDicomNode()->GetType()+1))
1076 /* std::cout << "Sorting using '"
1077 << mSettings.GetActiveComparator
1078 (item->GetDicomNode()->GetType()+1).GetName()
1081 item->GetDicomNode()->SortChildren
1082 ( mSettings.GetActiveComparator
1083 (item->GetDicomNode()->GetType()+1)
1085 // std::cout << "ok"<<std::endl;
1088 DicomNode::ChildrenListType::iterator i;
1089 for (i=item->GetDicomNode()->GetChildrenList().begin();
1090 i!=item->GetDicomNode()->GetChildrenList().end();
1093 UpdateDicomNodeView(*i,id);
1096 // EO If children not already loaded
1100 //================================================================
1103 //================================================================
1104 void WxGimmick::OnItemExpanded(wxTreeEvent& event)
1107 // std::cout << "* Expanded *"<<std::endl;
1112 wxTreeItemId itemId = event.GetItem();
1113 LoadChildren(itemId);
1117 // expand if collapsed and collapse if expanded ...
1118 TreeItemData *item =
1119 (TreeItemData *)mTreeListCtrl->GetItemData(itemId);
1122 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1123 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1126 // If children not already loaded : do it
1128 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1129 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1133 // Some new children loaded
1135 if (mSettings.HasActiveComparator
1136 (item->GetDicomNode()->GetType()+1))
1138 /* std::cout << "Sorting using '"
1139 << mSettings.GetActiveComparator
1140 (item->GetDicomNode()->GetType()+1).GetName()
1143 item->GetDicomNode()->SortChildren
1144 ( mSettings.GetActiveComparator
1145 (item->GetDicomNode()->GetType()+1)
1147 // std::cout << "ok"<<std::endl;
1150 // If images : sort them
1151 if (item->IsDicomNode())
1153 if (item->GetDicomNode()->GetType()==DicomNode::Series)
1157 LexicographicalDicomNodeComparator compare;
1158 // DicomNodeImageImageNumberComparator c1;
1160 DicomNodeImageSliceLocationComparator c1;
1161 DicomNodeImageImageNumberComparator c2;
1162 DicomNodeImageFileNameComparator cn;
1166 // std::cout << "SORT"<<std::endl;
1167 item->GetDicomNode()->SortChildren(compare);
1168 // std::cout << "EO SORT"<<std::endl;
1176 DicomNode::ChildrenListType::iterator i;
1177 for (i=item->GetDicomNode()->GetChildrenList().begin();
1178 i!=item->GetDicomNode()->GetChildrenList().end();
1181 UpdateDicomNodeView(*i,itemId);
1184 // EO If children not already loaded
1187 // mTreeListCtrl->Expand(itemId);
1190 //================================================================
1194 //=====================================================================
1195 void WxGimmick::InsertRoot(wxTreeItemId& id, Root* r)
1198 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1203 data->GetDicomNode()->GetDicomDatabase()->LoadAll();
1204 printf(">>>>>> Time to load all = %ldms \n",sw.Time());
1206 UpdateRootView(data->GetDicomNode()->GetDicomDatabase());
1209 if (data->IsDicomNode())
1212 r->Insert(data->GetDicomNode());
1213 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1216 else if (data->IsDatabase())
1219 DicomNode::ChildrenListType::iterator j;
1220 for (j= data->GetDicomNode()->GetChildrenList().begin();
1221 j!=data->GetDicomNode()->GetChildrenList().end();
1226 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1232 //=====================================================================
1236 //=================================================
1237 void WxGimmick::DeleteDicomDatabase(wxTreeItemId& id,
1241 DicomDatabaseListType::iterator i = find(GetDicomDatabaseList().begin(),
1242 GetDicomDatabaseList().end(),
1245 GetDicomDatabaseList().erase(i);
1246 mTreeListCtrl->Delete(id);
1248 //=================================================
1252 //=====================================================================
1254 void WxGimmick::OnItemRightClick(wxTreeEvent& event)
1257 wxTreeItemId itemId = event.GetItem();
1260 wxPoint clientpt = event.GetPoint();
1261 wxPoint screenpt = ClientToScreen(clientpt);
1262 ShowMenu(itemId, clientpt);
1266 //=====================================================================
1270 //=====================================================================
1271 void WxGimmick::ShowMenu(wxTreeItemId id, const wxPoint& pt)
1274 // std::cout << "ShowMenu" <<std::endl;
1276 TreeItemData *data =
1277 (TreeItemData *)mTreeListCtrl->GetItemData(id);
1283 title << wxT("Menu for ") << mTreeListCtrl->GetItemText(id);
1287 title = wxT("Menu for no particular item");
1294 if (id==mCollectionsTitlesItemId)
1296 menu.Append(PopUp_NewCollection, _T("&New collection"));
1297 menu.Append(PopUp_OpenCollection, _T("&Open collection"));
1301 if (data->IsDatabase())
1303 wxMenu* addmenu = new wxMenu;
1304 addmenu->Append(PopUp_AddDirectory, _T("Scan &Directory"));
1305 addmenu->Append(PopUp_AddFile, _T("Select &File(s)"));
1306 // addmenu->Append(PopUp_AddRawFile, _T("Add &Raw image"));
1307 menu.AppendSubMenu(addmenu, _T("&Add image(s) to collection..."));
1308 menu.Append(PopUp_CloseCollection, _T("&Close collection"));
1309 menu.Append(PopUp_DeleteCollection, _T("&Delete collection"));
1311 if (data->IsDicomNode())
1316 std::string str("&Remove ");
1317 str += data->GetDicomNode()->GetTypeName();
1318 menu.Append(PopUp_Remove, std2wx(str));
1322 if ((data->GetDicomNode()>0)&&
1323 ( data->GetDicomNode()->GetType()<DicomNode::Image))
1325 int ctype = data->GetDicomNode()->GetType()+1;
1326 if (mSettings.HasActiveComparator(ctype))
1328 wxMenu* sortmenu = new wxMenu;
1330 Settings::ComparatorsList::iterator i;
1331 for (i =mSettings.GetComparatorsList(ctype).begin();
1332 i !=mSettings.GetComparatorsList(ctype).end();
1335 sortmenu->AppendRadioItem(PopUp_Sort+n, std2wx(i->GetName()));
1339 sortmenu->Check(PopUp_Sort+
1340 mSettings.GetActiveComparatorIndex(ctype)
1343 std::string sortmenustr("&Sort ");
1344 sortmenustr += DicomNode::GetPluralTypeName(ctype);
1345 sortmenustr += " by...";
1346 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1347 menu.AppendSubMenu(sortmenu,std2wx(sortmenustr));
1350 item->GetDicomNode()->SortChildren
1351 ( mSettings.GetActiveComparator
1352 (item->GetDicomNode()->GetType()+1)
1354 std::cout << "ok"<<std::endl;
1359 // Event : user can customize the menu
1361 ev(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU,this,id);
1365 ev.SetDicomNode(data->GetDicomNode());
1367 GetEventHandler()->ProcessEvent(ev);
1370 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1371 menu.Append(PopUp_Settings, wxT("&Settings..."));
1372 menu.Append(PopUp_About, wxT("&About..."));
1377 wxMenu* newmenu = new wxMenu;
1378 wxMenu* openmenu = new wxMenu;
1379 Tree::RootHandlerListType::iterator h;
1381 for (h= Tree::GetRootHandlerList().begin();
1382 h!=Tree::GetRootHandlerList().end();
1385 if ((*h)->SupportsNew())
1387 newmenu->Append(PopUp_New+i, std2wx((*h)->GetName()));
1389 if ((*h)->SupportsOpen())
1390 openmenu->Append(PopUp_Open+i, std2wx((*h)->GetName()));
1394 menu.AppendSubMenu(openmenu, _T("&Open"));
1395 menu.AppendSubMenu(newmenu, _T("&New"));
1399 if ((data->IsDatabase())||(data->IsDicomNode()))
1401 Root* itroot = data->GetDicomNode()->GetDicomDatabase();
1402 // if (!itroot) itroot = data->GetDicomNode()->GetRoot();
1403 wxMenu* insertmenu = new wxMenu;
1404 bool hasone = false;
1406 Tree::RootListType::iterator j;
1407 for (j = mTree->GetDatabaseList().begin();
1408 j != mTree->GetDatabaseList().end();
1411 // std::cout << (*j)->GetName() << " "
1412 // << (*j)->GetTypeName()
1413 // << " i="<<(*j)->SupportsInsert()<<std::endl;
1414 if ( ((*j)!=itroot) && ((*j)->SupportsInsert()) )
1416 insertmenu->Append(PopUp_Insert+i,
1417 std2wx((*j)->GetName()));
1423 if (hasone) menu.AppendSubMenu(insertmenu, _T("&Insert into"));
1425 if (data->IsDatabase())
1427 menu.Append(PopUp_Close, wxT("&Close"));
1429 if (data->IsDicomNode() && data->GetDicomNode()->GetDicomDatabase()->SupportsRemove())
1431 menu.Append(PopUp_Remove, wxT("&Remove"));
1439 PopupMenu(&menu, pt);
1440 #endif // wxUSE_MENUS
1442 // std::cout << "EO ShowMenu" <<std::endl;
1444 //=====================================================================
1446 //=====================================================================
1447 // Pop up menu callbacks
1448 void WxGimmick::OnPopUpAbout(wxCommandEvent& event)
1450 wxMessageBox( _T("Give me my medical images quick ! \n\n (c) CREATIS-LRMN 2008\n laurent.guigues@creatis.insa-lyon.fr"),
1452 wxOK | wxICON_INFORMATION, this);
1454 //=====================================================================
1456 //=====================================================================
1457 void WxGimmick::OnPopUpSettings(wxCommandEvent& event)
1459 WxGimmickSettingsDialog* s =
1460 new WxGimmickSettingsDialog(this,&mSettings);
1464 //=====================================================================
1466 //=====================================================================
1467 void WxGimmick::OnPopUpNewCollection(wxCommandEvent& event)
1470 OpenOrNewDatabase(false);
1472 //=====================================================================
1476 //=====================================================================
1477 void WxGimmick::OnPopUpOpenCollection(wxCommandEvent& event)
1480 OpenOrNewDatabase(true);
1482 //=====================================================================
1485 //=====================================================================
1486 void WxGimmick::OnPopUpCloseCollection(wxCommandEvent& event)
1488 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;
1491 // std::cout << "OnPopUpClose"<<std::endl;
1492 // wxTreeItemId id = event.GetId();
1493 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1494 DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
1495 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1496 DeleteDicomDatabase(mItemOfMenu,r);
1498 //=====================================================================
1500 //=====================================================================
1501 void WxGimmick::OnPopUpDeleteCollection(wxCommandEvent& event)
1503 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;
1508 // std::cout << "OnPopUpClose"<<std::endl;
1509 // wxTreeItemId id = event.GetId();
1510 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1511 DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
1513 wxRemoveFile(std2wx(r->GetFileName()));
1514 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1515 DeleteDicomDatabase(mItemOfMenu,r);
1518 //=====================================================================
1520 void DisplayUpdateSummary( DicomDatabase::UpdateSummary& summary,
1523 std::stringstream mess;
1524 mess << "Dirs\tscanned\t\t\t: " << summary.scanned_dirs << "\n";
1525 mess << "Files\tscanned\t\t\t: " << summary.scanned_files << "\n";
1526 mess << "Files\thandled\t\t\t: " << summary.handled_images << "\n\n";
1527 mess << "Patients\tadded\t\t: " << summary.added_patients<< "\n";
1528 mess << "Studies\tadded\t\t: " << summary.added_studies<< "\n";
1529 mess << "Series\tadded\t\t: " << summary.added_series<< "\n";
1530 mess << "Images\tadded\t\t: " << summary.added_images<< "\n\n";
1532 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",
1534 (int)( summary.parse_time*100./summary.total_time),
1535 summary.file_scan_time,
1536 (int)(summary.file_scan_time*100./summary.total_time),
1537 summary.update_structs_time,
1538 (int)(summary.update_structs_time*100./summary.total_time),
1539 summary.update_database_time,
1540 (int)(summary.update_database_time*100./summary.total_time),
1541 summary.total_time );
1545 wxMessageBox(std2wx(mess.str()),_T("Update summary"),wxOK,parent);
1549 //=====================================================================
1550 void WxGimmick::OnPopUpAddFile(wxCommandEvent& event)
1552 long style = wxOPEN | wxFILE_MUST_EXIST | wxFD_MULTIPLE;
1553 std::string wc("*.*");
1554 wxFileDialog* FD = new wxFileDialog( 0,
1562 if (FD->ShowModal()==wxID_OK)
1566 mCurrentDirectory = FD->GetDirectory();
1567 wxArrayString files;
1568 FD->GetPaths(files);
1570 std::vector<std::string> filenames;
1571 for (i=0;i<files.GetCount();++i)
1572 filenames.push_back(wx2std(files[i]));
1575 TreeItemData *data =
1577 mTreeListCtrl->GetItemData(mItemOfMenu);
1578 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1579 DicomDatabase::UpdateSummary summary;
1580 wxProgressDialog* progress =
1581 new wxProgressDialog(_T("Adding file(s)"),
1586 wxPD_ESTIMATED_TIME |
1587 wxPD_REMAINING_TIME |
1590 db->AddFiles(filenames,progress,summary);
1592 progress->Pulse(_T("Updating view..."));
1593 UpdateDicomDatabaseView(db);
1595 DisplayUpdateSummary(summary,this);
1599 //=====================================================================
1601 //=====================================================================
1602 void WxGimmick::OnPopUpAddRawFile(wxCommandEvent& event)
1604 wxMessageBox(_T("Not yet implemented !"),_T("Sorry"),wxOK,this);
1606 //=====================================================================
1608 //=====================================================================
1609 void WxGimmick::OnPopUpAddDirectory(wxCommandEvent& event)
1611 long style = wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST;
1614 _T("Select directory"),
1618 if (FD->ShowModal()==wxID_OK)
1621 bool recurse = false;
1622 if (wxMessageBox(_T("Recurse into sub-directories ?"),
1623 _T("Scan directory"),
1624 wxYES_NO,this ) == wxYES)
1630 wxProgressDialog* progress =
1631 new wxProgressDialog(_T("Scanning directory"),
1632 _T("Parsing directory"),
1636 wxPD_ESTIMATED_TIME |
1637 wxPD_REMAINING_TIME |
1639 DicomDatabase::UpdateSummary summary;
1641 std::string dirname = wx2std (FD->GetPath()) ;
1642 mCurrentDirectory = FD->GetPath();
1643 TreeItemData *data =
1645 mTreeListCtrl->GetItemData(mItemOfMenu);
1646 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1647 db->AddDirectory(dirname,recurse,progress,summary);
1649 progress->Pulse(_T("Updating view..."));
1650 UpdateDicomDatabaseView(db);
1653 DisplayUpdateSummary(summary,this);
1655 if (summary.cancelled_by_user)
1657 std::cout << "!! Cancelled by user !!"<<std::endl;
1663 //=====================================================================
1665 //=====================================================================
1666 void WxGimmick::OnPopUpRemove(wxCommandEvent& event)
1670 wxMessageBox(_T("Not yet implemented"),_T("Sorry !"),wxOK);
1674 // wxTreeItemId id = event.GetId();
1675 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1677 std::string mess("Remove ");
1678 mess += data->GetDicomNode()->GetTypeName();
1679 mess += " from collection ?";
1680 int answer = wxMessageBox(std2wx(mess), _T("Confirm"), wxYES_NO);
1681 if (answer == wxNO) return;
1683 if ( mTreeListCtrl->IsSelected(mItemOfMenu) )
1685 wxTreeItemId next = mTreeListCtrl->GetNextSibling(mItemOfMenu);
1688 mTreeListCtrl->SelectItem(next);
1696 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1697 db->Remove(data->GetDicomNode());
1698 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1699 // TODO : Optimize update only parent's branch
1700 UpdateDicomDatabaseView(db);
1701 // DeleteDicomDatabase(mItemOfMenu,r);
1703 //=====================================================================
1705 //=====================================================================
1706 void WxGimmick::OnPopUpSort(wxCommandEvent& event)
1709 // std::cout << "OnPopUpSort"<<std::endl;
1710 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1711 int index = event.GetId() - PopUp_Sort;
1712 DicomNode* node = data->GetDicomNode();
1713 DicomNode::Type ctype = node->GetType()+1;
1714 mSettings.SetActiveComparatorIndex(ctype,index);
1716 if (node->ChildrenLoaded())
1719 mTreeListCtrl->DeleteChildren(mItemOfMenu);
1721 /* std::cout << "Sorting using '"
1722 << mSettings.GetActiveComparator(ctype).GetName()
1725 node->SortChildren ( mSettings.GetActiveComparator(ctype) );
1726 // std::cout << "ok"<<std::endl;
1730 CreateChildrenColumnsTitles(mItemOfMenu,ctype);
1731 DicomNode::ChildrenListType::iterator i;
1732 for (i=node->GetChildrenList().begin();
1733 i!=node->GetChildrenList().end();
1736 UpdateDicomNodeView(*i,mItemOfMenu);
1740 //=====================================================================
1743 //=====================================================================
1744 void WxGimmick::OnPopUpUser(wxCommandEvent& event)
1746 // std::cout << "OnPopUpUser"<<std::endl;
1749 //=====================================================================
1751 //=================================================
1752 void WxGimmick::CreateImageList(int size)
1756 mTreeListCtrl->SetImageList(NULL);
1765 // should correspond to Icon_xxx enum
1766 icons[Icon_Patient] = wxIcon(patient_xpm);
1767 icons[Icon_Study] = wxIcon(study_xpm);
1768 icons[Icon_Series] = wxIcon(series_xpm);
1769 icons[Icon_Image] = wxIcon(image_xpm);
1770 icons[Icon_Database] = wxIcon(database_xpm);
1771 icons[Icon_Folder] = wxIcon(folder_xpm);
1772 icons[Icon_DicomDir] = wxIcon(dicomdir_xpm);
1773 icons[Icon_Root] = wxIcon(root_xpm);
1776 // mFirstRootIconIndex = 8;
1779 Tree::RootHandlerListType::iterator h;
1781 for (h= Tree::GetDatabaseHandlerList().begin();
1782 h!=Tree::GetDatabaseHandlerList().end();
1785 icons[mFirstRootIconIndex+i] = (*h)->GetIcon();
1789 unsigned int NbIcons = 8;//mFirstRootIconIndex + i;
1790 // Make an image list containing small icons
1791 wxImageList *images = new wxImageList(size, size, true);
1793 int sizeOrig = icons[0].GetWidth();
1794 for ( size_t i = 0; i < NbIcons; i++ )
1796 if ( size == sizeOrig )
1798 images->Add(icons[i]);
1802 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
1805 mTreeListCtrl->AssignImageList(images);
1807 //=================================================
1816 //================================================================
1817 bool WxGimmick::IsImageSelectable(DicomNode* node)
1819 int rows = node->ImageGetRows();
1820 int cols = node->ImageGetColumns();
1821 int frms = node->ImageGetFrames();
1823 // std::cout << "R/C/F = " << rows << "/"<< cols <<"/"<<frms<<std::endl;
1827 else if (cols>0) dim=2;
1828 else if (rows>0) dim=1;
1832 std::cout << "Unknown image dimension : cannot select !"
1836 else if (dim>mSelectionMaxImageDimension)
1838 std::cout << "Selecting "<<dim<<"D images is not allowed !"
1843 if ( mTreeListCtrl->GetSelectionSize() == 0 )
1845 mCurrentSelectionImageSize[0] = cols;
1846 mCurrentSelectionImageSize[1] = rows;
1847 mCurrentSelectionImageSize[2] = frms;
1852 if ( dim == mSelectionMaxImageDimension )
1854 std::cout << "Cannot add this image to selection : would result in a "<<dim+1<<"D image !" << std::endl;
1857 if ( ( cols != mCurrentSelectionImageSize[0] ) ||
1858 ( rows != mCurrentSelectionImageSize[1] ) ||
1859 ( frms != mCurrentSelectionImageSize[2] ) )
1861 std::cout << "Cannot add this image to selection : image size is incomptatible with currently selected images" << std::endl;
1865 // std::cout << "Selecting : "<<node->ImageGetFullFileName() << std::endl;
1868 //================================================================
1870 //================================================================
1871 void WxGimmick::OnSelChanging(wxTreeEvent& event)
1874 wxTreeItemId id = event.GetItem();
1877 std::cout << "INTERNAL ERROR : ID NOT OK"<<std::endl;
1882 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1883 if (data->IsDicomNode())
1885 if (data->GetDicomNode()>0)
1887 // An image was selected
1888 if (data->GetDicomNode()->GetType()==DicomNode::Image)
1890 if (IsImageSelectable(data->GetDicomNode())) event.Allow();
1892 // A series was selected
1893 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
1895 // If images not loaded do it
1897 // can be selected if all its images can
1899 wxTreeItemIdValue cookie;
1900 for (child = mTreeListCtrl->GetFirstChild(id,cookie);
1902 child = mTreeListCtrl->GetNextChild(id,cookie))
1904 TreeItemData *cdata =
1905 (TreeItemData *)mTreeListCtrl->GetItemData(child);
1906 if ((cdata->IsDicomNode())&&
1907 (cdata->GetDicomNode()>0)&&
1908 (cdata->GetDicomNode()->GetType()==DicomNode::Image)&&
1909 (!IsImageSelectable(cdata->GetDicomNode())))
1917 //================================================================
1919 //================================================================
1920 void WxGimmick::OnSelChanged(wxTreeEvent& event)
1922 // wxBusyCursor busy;
1923 // std::vector<wxTreeItemId> items;
1924 // GetSelectedItems(items);
1926 std::vector<DicomNode*>::iterator i;
1927 for (i=nodes.begin();i!=nodes.end();++i)
1929 std::cout << "'" << (*i)->GetFieldValue("FullFileName")
1930 << "'" << std::endl;
1932 std::cout << "++++++++++++++++++++" << std::endl;
1934 // ShowImage(mReader.GetImage(""));
1936 bool no_image = true;
1938 static int max = 1000;
1941 // if (items.size()>0)
1944 // Update image preview : send requests to the MTImageReader
1945 // bool first = true;
1946 // std::vector<wxTreeItemId>::iterator i;
1947 // for (i=items.begin();i!=items.end();++i)
1953 DicomNode* node = GetDicomNodeOfItem(items[0]);
1955 // Update dicom fields panel
1956 mFieldsView->UpdateValues(node);
1960 wxTreeItemId item = mTreeListCtrl->GetCurrent();
1962 DicomNode* n = GetDicomNodeOfItem(item);
1964 if (n) mFieldsView->UpdateValues(n);
1967 (n->GetType()==DicomNode::Image) )
1972 //if (i==items.begin())
1973 mCurImageItemToShow = item;
1975 int maxprio = mReader.GetMaximalPriority();
1976 int prio = maxprio + 1000;
1977 wxTreeItemId sib = item; //GetTreeListCtrl()->GetNextSibling(*i);
1980 DicomNode* nsib = GetDicomNodeOfItem(sib);
1983 // std::cout << "-- Request '"
1984 // << nsib->GetFieldValue("FullFileName")
1985 // << "' prio="<<prio<<std::endl;
1986 mReader.Request(this,
1987 nsib->ImageGetFullFileName(),
1989 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
1993 sib = GetTreeListCtrl()->GetNextSibling(sib);
1995 prio = maxprio + 1000;
1996 sib = GetTreeListCtrl()->GetPrevSibling(item);
1999 DicomNode* nsib = GetDicomNodeOfItem(sib);
2002 // std::cout << "-- Request '"
2003 // << nsib->GetFieldValue("FullFileName")
2004 // << "' prio="<<prio<<std::endl;
2005 mReader.Request(this,
2006 nsib->ImageGetFullFileName(),
2008 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
2012 sib = GetTreeListCtrl()->GetPrevSibling(sib);
2014 // mImageFileNameToNode[n->GetFieldValue("FullFileName")] = n;
2017 ProcessImageEvents();
2019 // std::cout << "* Selection changed * (im)"<<std::endl;
2021 //---------------------------------------------------------------------
2023 WxGimmickEvent ev(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED,
2027 GetEventHandler()->ProcessEvent(ev);
2029 if (no_image) ShowImage(mReader.GetImage(""));
2032 //================================================================
2034 //================================================================
2035 void WxGimmick::ShowImage(vtkImageData* im)
2037 // wxBusyCursor busy;
2039 int x1,x2,y1,y2,z1,z2;
2041 im->GetSpacing(spx,spy,spz);
2042 im->GetExtent (x1,x2,y1,y2,z1,z2);
2045 std::cout << x1 << "-"<<x2<<std::endl;
2046 std::cout << y1 << "-"<<y2<<std::endl;
2047 std::cout << z1 << "-"<<z2<<std::endl;
2048 std::cout << spx << "-"<<spy<<"-"<<spz<<std::endl;
2072 vtkCamera *camera = mViewer->GetRenderer()->GetActiveCamera();
2074 camera->SetViewUp ( spx*0, -spy*1, spz*0);
2075 camera->SetPosition( spx*(x1+x2)/2, spy*(y1+y2)/2, -spz*10000000);
2076 camera->SetFocalPoint ( spx*(x1+x2)/2 , spy*(y1+y2)/2 , spz*0);
2078 camera->ComputeViewPlaneNormal();
2079 camera->SetParallelScale( spx*(x2-x1)/2.0 );
2083 mViewer->SetInput( im );
2084 mViewer->SetSlice( 0 );
2085 mInteractor->Render();
2087 //================================================================
2094 //================================================================
2096 OnMultiThreadImageReaderEvent(const std::string& filename,
2097 MultiThreadImageReaderUser::EventType e,
2098 vtkImageData* image)
2100 if (filename.size()==0)
2102 mImageEventQueue.push_back(ImageEventType(image));
2105 std::map<std::string,DicomNode*>::iterator i;
2106 i = mImageFileNameToNode.find(filename);
2107 if (i!=mImageFileNameToNode.end())
2109 wxTreeItemId id = i->second->GetData<NodeData*>()->GetTreeItemData()->GetItemId();
2110 mImageEventQueue.push_back(ImageEventType(id,image));
2113 //================================================================
2115 //================================================================
2116 // Processes the queue of image events
2117 void WxGimmick::ProcessImageEvents()
2119 // std::cout << "++++++++++ ProcessImageEvents " << std::endl;
2120 MultiThreadImageReaderEventLock();
2123 while (!mImageEventQueue.empty())
2125 ImageEventType e = mImageEventQueue.front();
2126 mImageEventQueue.pop_front();
2131 mTreeListCtrl->SetItemTextColour(e.item,
2132 mSettings.LoadedImageColour());//wxImageLoadedColour);
2133 TreeItemData *data =
2134 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2135 data->SetLoaded(true);
2137 if (mCurImageItemToShow == e.item)
2142 else if (!mCurImageItemToShow.IsOk())
2147 else if (e.item.IsOk())
2149 mTreeListCtrl->SetItemTextColour(e.item,mSettings.Colour(DicomNode::Image)); //.wxImageUnloadedColour);
2150 TreeItemData *data =
2151 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2152 data->SetLoaded(false);
2155 mImageEventQueue.clear();
2156 MultiThreadImageReaderEventUnlock();
2157 // std::cout << "++++++++++ END ProcessImageEvents " << std::endl;
2159 //================================================================
2161 //================================================================
2162 void WxGimmick::OnInternalIdle()
2164 ProcessImageEvents();
2169 mJustStarted = false;
2174 //================================================================
2177 //================================================================
2178 // LG : For the moment any selection is valid but in the future
2179 // incomplete selections can be invalid...
2180 bool WxGimmick::IsSelectionValid()
2182 return (mTreeListCtrl->GetSelectionSize()>0);
2184 //================================================================
2186 //================================================================
2187 void WxGimmick::GetSelectedFiles(std::vector<std::string>& f)
2189 wxArrayTreeItemIds id;
2190 // TO DO : TEST THAT STYLE IS MULTIPLE
2191 unsigned int nb = mTreeListCtrl->GetSelections(id);
2193 for (unsigned int i=0; i<nb; ++i)
2195 TreeItemData *data =
2196 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2197 if ((data) && (data->IsDicomNode()))
2199 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2201 f.push_back ( data->GetDicomNode()->ImageGetFullFileName() );
2203 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2205 DicomNode::ChildrenListType::iterator j;
2206 for (j =data->GetDicomNode()->GetChildrenList().begin();
2207 j!=data->GetDicomNode()->GetChildrenList().end();
2210 f.push_back((*j)->ImageGetFullFileName());
2216 //================================================================
2218 //================================================================
2219 void WxGimmick::GetSelectedImages(std::vector<vtkImageData*>& f)
2221 wxArrayTreeItemIds id;
2222 // TO DO : TEST THAT STYLE IS MULTIPLE
2223 unsigned int nb = mTreeListCtrl->GetSelections(id);
2226 // Collect the brute vector of Image nodes
2227 std::vector<DicomNode*> im;
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 im.push_back ( data->GetDicomNode() );
2239 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2241 DicomNode::ChildrenListType::iterator j;
2242 for (j =data->GetDicomNode()->GetChildrenList().begin();
2243 j!=data->GetDicomNode()->GetChildrenList().end();
2246 im.push_back ( *j );
2251 // Create the output data
2254 // Only one image : give it
2255 vtkImageData* out = vtkImageData::New();
2256 out->ShallowCopy(mReader.GetImage(im.front()->ImageGetFullFileName()));
2259 else if (im.size()>1)
2261 vtkImageData* first = mReader.GetImage( im.front()->ImageGetFullFileName() );
2262 if (first->GetDataDimension()==2)
2265 vtkImageData* out = vtkImageData::New();
2266 out->CopyStructure(first);
2267 out->SetScalarType(first->GetScalarType());
2269 first->GetExtent(ext);
2271 out->SetExtent(ext);
2272 // LG : TODO : Z Spacing ?
2274 out->AllocateScalars();
2276 //first->Print(std::cout);
2277 // out->Print(std::cout);
2280 first->GetDimensions(dim);
2281 unsigned long imsize =
2282 ( (unsigned long)first->GetScalarPointer(0,1,0)
2283 - (unsigned long)first->GetScalarPointer(0,0,0))
2287 std::vector<DicomNode*>::iterator it;
2288 for (it=im.begin(); it!=im.end(); ++it)
2290 //std::cout << "copying slice "<<slice <<std::endl;
2291 vtkImageData* cur = mReader.GetImage( (*it)->ImageGetFullFileName() );
2293 void* src = cur->GetScalarPointer(0,0,0);
2294 void* dst = out->GetScalarPointer(0,0,slice);
2295 // std::cout << "src="<<src<<std::endl;
2296 // std::cout << "dst="<<dst<<std::endl;
2297 // std::cout << "siz="<<imsize<<std::endl;
2298 memcpy(dst,src,imsize);
2303 for (ii=1;ii<4;ii++) {
2304 for (jj=1;jj<4;jj++) {
2305 int x = (int)(ii*dim[0] / 4);
2306 int y = (int)(jj*dim[1] / 4);
2307 std::cout << cur->GetScalarComponentAsFloat(x,y,0,0)
2309 << out->GetScalarComponentAsFloat(x,y,slice,0)
2322 std::vector<DicomNode*>::iterator it;
2323 for (it=im.begin(); it!=im.end(); ++it)
2325 vtkImageData* out = vtkImageData::New();
2326 out->ShallowCopy(mReader.GetImage((*it)->ImageGetFullFileName()));
2332 //================================================================
2335 //================================================================
2336 void WxGimmick::GetSelectedDicomNodes(std::vector<DicomNode*>& f)
2338 wxArrayTreeItemIds id;
2339 // TO DO : TEST THAT STYLE IS MULTIPLE
2340 unsigned int nb = mTreeListCtrl->GetSelections(id);
2342 for (unsigned int i=0; i<nb; ++i)
2344 TreeItemData *data =
2345 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2346 if ((data) && (data->IsDicomNode()))
2348 f.push_back ( data->GetDicomNode() );
2352 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2354 f.push_back ( data->GetDicomNode() ); //->ImageGetFullFileName() );
2356 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2358 DicomNode::ChildrenListType::iterator j;
2359 for (j =data->GetDicomNode()->GetChildrenList().begin();
2360 j!=data->GetDicomNode()->GetChildrenList().end();
2363 f.push_back((*j)); //->ImageGetFullFileName() ); }
2369 //================================================================
2371 //================================================================
2372 void WxGimmick::GetSelectedItems(std::vector<wxTreeItemId>& f)
2374 wxArrayTreeItemIds id;
2375 // TO DO : TEST THAT STYLE IS MULTIPLE
2376 unsigned int nb = mTreeListCtrl->GetSelections(id);
2378 for (unsigned int i=0; i<nb; ++i)
2383 //================================================================
2385 //================================================================
2386 DicomNode* WxGimmick::GetDicomNodeOfItem(const wxTreeItemId& i)
2388 TreeItemData *data =
2389 (TreeItemData *)mTreeListCtrl->GetItemData(i);
2390 if (data) return ( data->GetDicomNode() );
2393 //================================================================
2395 //================================================================
2396 //================================================================
2397 //================================================================
2398 //================================================================
2414 //================================================================
2415 //================================================================
2416 //================================================================
2417 //================================================================
2419 BEGIN_EVENT_TABLE(WxGimmick, wxPanel)
2421 EVT_MENU(PopUp_NewCollection,WxGimmick::OnPopUpNewCollection)
2422 EVT_MENU(PopUp_OpenCollection,WxGimmick::OnPopUpOpenCollection)
2423 EVT_MENU(PopUp_CloseCollection,WxGimmick::OnPopUpCloseCollection)
2424 EVT_MENU(PopUp_DeleteCollection,WxGimmick::OnPopUpDeleteCollection)
2425 EVT_MENU(PopUp_AddFile, WxGimmick::OnPopUpAddFile)
2426 EVT_MENU(PopUp_AddRawFile, WxGimmick::OnPopUpAddRawFile)
2427 EVT_MENU(PopUp_AddDirectory, WxGimmick::OnPopUpAddDirectory)
2428 EVT_MENU(PopUp_Remove, WxGimmick::OnPopUpRemove)
2429 EVT_MENU(PopUp_About, WxGimmick::OnPopUpAbout)
2430 EVT_MENU(PopUp_Settings, WxGimmick::OnPopUpSettings)
2432 EVT_MENU_RANGE(PopUp_Sort, PopUp_Sort+99, WxGimmick::OnPopUpSort)
2433 EVT_MENU_RANGE(PopUp_User, PopUp_User+99, WxGimmick::OnPopUpUser)
2438 EVT_TREE_BEGIN_DRAG(TreeListCtrlId, WxGimmick::OnBeginDrag)
2439 EVT_TREE_BEGIN_RDRAG(TreeListCtrlId, WxGimmick::OnBeginRDrag)
2440 EVT_TREE_END_DRAG(TreeListCtrlId, WxGimmick::OnEndDrag)
2443 EVT_TREE_BEGIN_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnBeginLabelEdit)
2444 EVT_TREE_END_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnEndLabelEdit)
2447 EVT_TREE_DELETE_ITEM(TreeListCtrlId, WxGimmick::OnDeleteItem)
2448 #if 0 // there are so many of those that logging them causes flicker
2449 EVT_TREE_GET_INFO(TreeListCtrlId, WxGimmick::OnGetInfo)
2452 EVT_TREE_SET_INFO(TreeListCtrlId, WxGimmick::OnSetInfo)
2455 EVT_TREE_ITEM_EXPANDED(TreeListCtrlId, WxGimmick::OnItemExpanded)
2456 EVT_TREE_ITEM_EXPANDING(TreeListCtrlId, WxGimmick::OnItemExpanding)
2457 EVT_TREE_ITEM_COLLAPSED(TreeListCtrlId, WxGimmick::OnItemCollapsed)
2458 EVT_TREE_ITEM_COLLAPSING(TreeListCtrlId, WxGimmick::OnItemCollapsing)
2461 EVT_TREE_SEL_CHANGED(TreeListCtrlId, WxGimmick::OnSelChanged)
2462 EVT_TREE_SEL_CHANGING(TreeListCtrlId, WxGimmick::OnSelChanging)
2464 EVT_TREE_KEY_DOWN(TreeListCtrlId, WxGimmick::OnTreeKeyDown)
2465 // ACTIVATION = DOUBLE CLICK OR ENTER ON SELECTED
2466 EVT_TREE_ITEM_ACTIVATED(TreeListCtrlId, WxGimmick::OnItemActivated)
2468 // so many differents ways to handle right mouse button clicks...
2469 // EVT_CONTEXT_MENU(WxGimmick::OnContextMenu)
2470 // EVT_TREE_ITEM_MENU is the preferred event for creating context menus
2471 // on a tree control, because it includes the point of the click or item,
2472 // meaning that no additional placement calculations are required.
2473 // EVT_TREE_ITEM_MENU(TreeListCtrlId, WxGimmick::OnItemMenu)
2475 EVT_TREE_ITEM_RIGHT_CLICK(TreeListCtrlId, WxGimmick::OnItemRightClick)
2478 // EVT_RIGHT_DOWN(WxGimmick::OnRMouseDown)
2479 // EVT_RIGHT_UP(WxGimmick::OnRMouseUp)
2480 // EVT_RIGHT_DCLICK(WxGimmick::OnRMouseDClick)
2483 //IMPLEMENT_DYNAMIC_CLASS(WxGimmick, wxTreeListCtrl)
2486 wxTree::wxTree(wxWindow *parent, const wxWindowID id,
2487 const wxPoint& pos, const wxSize& size,
2489 : wxTreeListCtrl(parent, id, pos, size, style)
2491 m_reverseSort = false;
2495 // Add some items to the tree
2496 AddTestItemsToTree(5, 2);
2502 #if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
2503 void WxGimmick::CreateButtonsImageList(int size)
2508 mTreeListCtrl->SetButtonsImageList(NULL);
2512 // Make an image list containing small icons
2513 wxImageList *images = new wxImageList(size, size, true);
2515 // should correspond to TreeListCtrlIcon_xxx enum
2518 icons[0] = wxIcon(icon3_xpm); // closed
2519 icons[1] = wxIcon(icon3_xpm); // closed, selected
2520 icons[2] = wxIcon(icon5_xpm); // open
2521 icons[3] = wxIcon(icon5_xpm); // open, selected
2523 for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
2525 int sizeOrig = icons[i].GetWidth();
2526 if ( size == sizeOrig )
2528 images->Add(icons[i]);
2532 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
2536 mTreeListCtrl->AssignButtonsImageList(images);
2539 void WxGimmick::CreateButtonsImageList(int WXUNUSED(size))
2545 int WxGimmick::OnCompareItems(const wxTreeItemId& item1,
2546 const wxTreeItemId& item2)
2548 if ( m_reverseSort )
2550 // just exchange 1st and 2nd items
2551 return mTreeListCtrl->OnCompareItems(item2, item1);
2555 return mTreeListCtrl->OnCompareItems(item1, item2);
2560 void WxGimmick::DoToggleIcon(const wxTreeItemId& item)
2563 int image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_Folder)
2566 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Normal);
2568 image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_FolderSelected)
2569 ? TreeIcon_FileSelected
2570 : TreeIcon_FolderSelected;
2571 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Selected);
2574 void WxGimmick::LogEvent(const wxChar *name, const wxTreeEvent& event)
2576 wxTreeItemId item = event.GetItem();
2579 text << _T('"') << mTreeListCtrl->GetItemText(item).c_str() << _T('"');
2581 text = _T("invalid item");
2582 // wxLogMessage(wxT("%s(%s)"), name, text.c_str());
2587 #define TREE_EVENT_HANDLER(name) \
2588 void WxGimmick::name(wxTreeEvent& event) \
2590 /* LogEvent(_T(#name), event); */ \
2591 /* SetLastItem(mTreeListCtrl->wxTreeItemId()) *;*/ \
2595 TREE_EVENT_HANDLER(OnBeginRDrag)
2596 TREE_EVENT_HANDLER(OnDeleteItem)
2597 TREE_EVENT_HANDLER(OnGetInfo)
2598 TREE_EVENT_HANDLER(OnSetInfo)
2599 //TREE_EVENT_HANDLER(OnItemExpanded)
2600 TREE_EVENT_HANDLER(OnItemExpanding)
2601 //TREE_EVENT_HANDLER(OnItemCollapsed)
2602 //TREE_EVENT_HANDLER(OnSelChanged)
2603 // TREE_EVENT_HANDLER(OnSelChanging)
2606 void WxGimmick::OnItemCollapsed(wxTreeEvent& event)
2608 // std::cout << "* Collapsed *"<<std::endl;
2611 #undef TREE_EVENT_HANDLER
2613 void WxGimmick::OnTreeKeyDown(wxTreeEvent& event)
2616 // LogKeyEvent(wxT("Tree key down "), event.GetKeyEvent());
2617 std::cout << "* Key down *"<<std::endl;
2618 if (event.GetKeyCode()==WXK_RIGHT)
2620 std::cout << "Right"<<std::endl;
2621 wxTreeItemId itemId = mTreeListCtrl->GetSelection();
2624 std::cout << "item is ok"<<std::endl;
2625 wxPoint clientpt = event.GetPoint();
2626 wxPoint screenpt = ClientToScreen(clientpt);
2627 ShowMenu(itemId, clientpt);
2632 std::cout << "NOT Right"<<std::endl;
2637 void WxGimmick::OnBeginDrag(wxTreeEvent& event)
2639 wxTreeItemId id = event.GetItem();
2640 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2641 // std::cout << "OnBeginDrag("<<id<<")"<<std::endl;
2642 if (data->IsDatabase())
2644 // std::cout << "-- IS ROOT"<<std::endl;
2647 else if (data->IsDicomNode())
2649 // std::cout << "-- IS NODE"<<std::endl;
2652 // need to explicitly allow drag
2653 if ( event.GetItem() != GetDatabaseItem() )
2655 m_draggedItem = event.GetItem();
2657 wxPoint clientpt = event.GetPoint();
2658 wxPoint screenpt = ClientToScreen(clientpt);
2660 wxLogMessage(wxT("OnBeginDrag: started dragging %s at screen coords (%i,%i)"),
2661 GetItemText(m_draggedItem).c_str(),
2662 screenpt.x, screenpt.y);
2668 wxLogMessage(wxT("OnBeginDrag: this item can't be dragged."));
2673 void WxGimmick::OnEndDrag(wxTreeEvent& event)
2675 wxTreeItemId id = event.GetItem();
2676 // std::cout << "OnEndDrag("<<id<<")"<<std::endl;
2677 if (!id.IsOk()) return;
2678 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2679 if (data->IsDatabase())
2681 // std::cout << "-- IS ROOT"<<std::endl;
2683 else if (data->IsDicomNode())
2685 // std::cout << "-- IS NODE"<<std::endl;
2689 wxTreeItemId itemSrc = m_draggedItem,
2690 itemDst = event.GetItem();
2691 m_draggedItem = (wxTreeItemId)0l;
2693 // where to copy the item?
2694 if ( itemDst.IsOk() && !ItemHasChildren(itemDst) )
2696 // copy to the parent then
2697 itemDst = GetItemParent(itemDst);
2700 if ( !itemDst.IsOk() )
2702 wxLogMessage(wxT("OnEndDrag: can't drop here."));
2707 wxString text = GetItemText(itemSrc);
2708 wxLogMessage(wxT("OnEndDrag: '%s' copied to '%s'."),
2709 text.c_str(), GetItemText(itemDst).c_str());
2711 // just do append here - we could also insert it just before/after the item
2712 // on which it was dropped, but this requires slightly more work... we also
2713 // completely ignore the client data and icon of the old item but could
2714 // copy them as well.
2716 // Finally, we only copy one item here but we might copy the entire tree if
2717 // we were dragging a folder.
2718 int image = wxGetApp().ShowImages() ? TreeIcon_File : -1;
2719 AppendItem(itemDst, text, image);
2724 //====================================================================
2725 void WxGimmick::OnBeginLabelEdit(wxTreeEvent& event)
2727 // std::cout << "OnBeginLabelEdit"<<std::endl;
2728 wxTreeItemId id = event.GetItem();
2729 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2730 // If not a root : veto
2731 if (data->IsDatabase())
2738 //====================================================================
2740 //====================================================================
2741 void WxGimmick::OnEndLabelEdit(wxTreeEvent& event)
2743 // std::cout << "OnEndLabelEdit"<<std::endl;
2744 wxTreeItemId id = event.GetItem();
2745 TreeItemData *data = GetItemData(id);
2746 // If not a database : bug !
2747 if (data->IsDatabase())
2749 data->GetDicomNode()->GetDicomDatabase()->SetName(wx2std(event.GetLabel()));
2750 mFieldsView->UpdateValues(data->GetDicomNode());
2754 std::cerr<< "!!!! Internal error : send bug report !!!!"<<std::endl;
2757 //====================================================================
2760 void WxGimmick::OnItemCollapsing(wxTreeEvent& event)
2762 // wxLogMessage(wxT("OnItemCollapsing"));
2764 // for testing, prevent the user from collapsing the first child folder
2765 wxTreeItemId itemId = event.GetItem();
2768 if ( IsTestItem(itemId) )
2770 wxMessageBox(wxT("You can't collapse this item."));
2778 //====================================================================
2779 void WxGimmick::ShowHelp()
2784 mHelpWindow = new WxGimmickHelpWindow(this);
2786 mHelpWindow->CenterOnParent();
2787 mHelpWindow->ShowModal();
2790 //====================================================================
2796 //================================================================
2797 //================================================================
2798 //================================================================
2799 //================================================================
2800 //================================================================
2802 //================================================================
2803 //================================================================
2804 //================================================================
2805 //================================================================
2806 //================================================================
2812 // ----------------------------------------------------------------------------
2814 // ----------------------------------------------------------------------------
2816 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_DRAG)
2817 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_RDRAG)
2818 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_DELETE_ITEM)
2819 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_GET_INFO)
2820 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SET_INFO)
2821 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDED)
2822 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDING)
2823 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSED)
2824 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSING)
2827 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT)
2828 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_LABEL_EDIT)
2831 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED)
2832 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGING)
2833 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_KEY_DOWN)
2834 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU)
2835 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_ITEM_STYLE_CHANGED)
2837 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_ACTIVATED)
2838 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK)
2839 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK)
2840 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_DRAG)
2841 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK)
2842 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP)
2843 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MENU)
2845 // ----------------------------------------------------------------------------
2847 // ----------------------------------------------------------------------------
2849 IMPLEMENT_ABSTRACT_CLASS(WxGimmickEvent, wxNotifyEvent)
2852 WxGimmickEvent::WxGimmickEvent(wxEventType commandType,
2854 const wxTreeItemId& item)
2856 wxNotifyEvent(commandType, tree->GetId()),
2860 // m_editCancelled = false;
2862 SetEventObject(tree);
2865 SetClientObject(tree->mTreeListCtrl->GetItemData(item));
2868 WxGimmickEvent::WxGimmickEvent(wxEventType commandType, int id)
2870 wxNotifyEvent(commandType, id),
2874 // m_editCancelled = false;
2877 WxGimmickEvent::WxGimmickEvent(const WxGimmickEvent & event)
2879 wxNotifyEvent(event),
2883 m_evtKey = event.m_evtKey;
2884 m_item = event.m_item;
2885 m_itemOld = event.m_itemOld;
2886 mColor = event.mColor;
2887 mUserData = event.mUserData;
2888 // m_pointDrag = event.m_pointDrag;
2889 // m_label = event.m_label;
2890 // m_editCancelled = event.m_editCancelled;
2900 //================================================================
2901 //================================================================
2902 //================================================================
2903 //================================================================
2904 //================================================================
2905 WxGimmickFrame::WxGimmickFrame( wxWindow *parent,
2908 : wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size)
2910 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
2911 mWxGimmick = new WxGimmick(this,-1,
2914 sizer->Add(mWxGimmick,1,wxGROW);
2916 SetAutoLayout(true);
2919 //================================================================
2921 //================================================================
2922 WxGimmickFrame::~WxGimmickFrame()
2925 //================================================================
2927 //================================================================
2928 void WxGimmickFrame::OnSelChanged(WxGimmickEvent& event)
2930 // std::cout << "+++++ WxGimmickFrame::OnSelChanged ++++++++++"
2932 std::vector<std::string> file;
2933 // mWxGimmick->GetSelectedImages(file);
2935 std::vector<std::string>::iterator i;
2936 for (i=file.begin();i!=file.end();++i)
2938 std::cout << "'" << *i << "'" << std::endl;
2940 std::cout << "++++++++++++++++++++" << std::endl;
2943 //================================================================
2945 //================================================================
2946 BEGIN_EVENT_TABLE(WxGimmickFrame, wxFrame)
2947 EVT_TREEVIEWLIST_SEL_CHANGED(-1,WxGimmickFrame::OnSelChanged)
2949 //================================================================