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 );
2081 camera->Roll ( 180 );
2084 mViewer->SetInput( im );
2085 mViewer->SetSlice( 0 );
2086 mInteractor->Render();
2088 //================================================================
2095 //================================================================
2097 OnMultiThreadImageReaderEvent(const std::string& filename,
2098 MultiThreadImageReaderUser::EventType e,
2099 vtkImageData* image)
2101 if (filename.size()==0)
2103 mImageEventQueue.push_back(ImageEventType(image));
2106 std::map<std::string,DicomNode*>::iterator i;
2107 i = mImageFileNameToNode.find(filename);
2108 if (i!=mImageFileNameToNode.end())
2110 wxTreeItemId id = i->second->GetData<NodeData*>()->GetTreeItemData()->GetItemId();
2111 mImageEventQueue.push_back(ImageEventType(id,image));
2114 //================================================================
2116 //================================================================
2117 // Processes the queue of image events
2118 void WxGimmick::ProcessImageEvents()
2120 // std::cout << "++++++++++ ProcessImageEvents " << std::endl;
2121 MultiThreadImageReaderEventLock();
2124 while (!mImageEventQueue.empty())
2126 ImageEventType e = mImageEventQueue.front();
2127 mImageEventQueue.pop_front();
2132 mTreeListCtrl->SetItemTextColour(e.item,
2133 mSettings.LoadedImageColour());//wxImageLoadedColour);
2134 TreeItemData *data =
2135 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2136 data->SetLoaded(true);
2138 if (mCurImageItemToShow == e.item)
2143 else if (!mCurImageItemToShow.IsOk())
2148 else if (e.item.IsOk())
2150 mTreeListCtrl->SetItemTextColour(e.item,mSettings.Colour(DicomNode::Image)); //.wxImageUnloadedColour);
2151 TreeItemData *data =
2152 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2153 data->SetLoaded(false);
2156 mImageEventQueue.clear();
2157 MultiThreadImageReaderEventUnlock();
2158 // std::cout << "++++++++++ END ProcessImageEvents " << std::endl;
2160 //================================================================
2162 //================================================================
2163 void WxGimmick::OnInternalIdle()
2165 ProcessImageEvents();
2170 mJustStarted = false;
2175 //================================================================
2178 //================================================================
2179 // LG : For the moment any selection is valid but in the future
2180 // incomplete selections can be invalid...
2181 bool WxGimmick::IsSelectionValid()
2183 return (mTreeListCtrl->GetSelectionSize()>0);
2185 //================================================================
2187 //================================================================
2188 void WxGimmick::GetSelectedFiles(std::vector<std::string>& f)
2190 wxArrayTreeItemIds id;
2191 // TO DO : TEST THAT STYLE IS MULTIPLE
2192 unsigned int nb = mTreeListCtrl->GetSelections(id);
2194 for (unsigned int i=0; i<nb; ++i)
2196 TreeItemData *data =
2197 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2198 if ((data) && (data->IsDicomNode()))
2200 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2202 f.push_back ( data->GetDicomNode()->ImageGetFullFileName() );
2204 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2206 DicomNode::ChildrenListType::iterator j;
2207 for (j =data->GetDicomNode()->GetChildrenList().begin();
2208 j!=data->GetDicomNode()->GetChildrenList().end();
2211 f.push_back((*j)->ImageGetFullFileName());
2217 //================================================================
2219 //================================================================
2220 void WxGimmick::GetSelectedImages(std::vector<vtkImageData*>& f)
2222 wxArrayTreeItemIds id;
2223 // TO DO : TEST THAT STYLE IS MULTIPLE
2224 unsigned int nb = mTreeListCtrl->GetSelections(id);
2227 // Collect the brute vector of Image nodes
2228 std::vector<DicomNode*> im;
2229 for (unsigned int i=0; i<nb; ++i)
2231 TreeItemData *data =
2232 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2233 if ((data) && (data->IsDicomNode()))
2235 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2237 im.push_back ( data->GetDicomNode() );
2240 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2242 DicomNode::ChildrenListType::iterator j;
2243 for (j =data->GetDicomNode()->GetChildrenList().begin();
2244 j!=data->GetDicomNode()->GetChildrenList().end();
2247 im.push_back ( *j );
2252 // Create the output data
2255 // Only one image : give it
2256 vtkImageData* out = vtkImageData::New();
2257 out->ShallowCopy(mReader.GetImage(im.front()->ImageGetFullFileName()));
2260 else if (im.size()>1)
2262 vtkImageData* first = mReader.GetImage( im.front()->ImageGetFullFileName() );
2263 if (first->GetDataDimension()==2)
2266 vtkImageData* out = vtkImageData::New();
2267 out->CopyStructure(first);
2268 out->SetScalarType(first->GetScalarType());
2270 first->GetExtent(ext);
2272 out->SetExtent(ext);
2273 // LG : TODO : Z Spacing ?
2275 out->AllocateScalars();
2277 //first->Print(std::cout);
2278 // out->Print(std::cout);
2281 first->GetDimensions(dim);
2282 unsigned long imsize =
2283 ( (unsigned long)first->GetScalarPointer(0,1,0)
2284 - (unsigned long)first->GetScalarPointer(0,0,0))
2288 std::vector<DicomNode*>::iterator it;
2289 for (it=im.begin(); it!=im.end(); ++it)
2291 //std::cout << "copying slice "<<slice <<std::endl;
2292 vtkImageData* cur = mReader.GetImage( (*it)->ImageGetFullFileName() );
2294 void* src = cur->GetScalarPointer(0,0,0);
2295 void* dst = out->GetScalarPointer(0,0,slice);
2296 // std::cout << "src="<<src<<std::endl;
2297 // std::cout << "dst="<<dst<<std::endl;
2298 // std::cout << "siz="<<imsize<<std::endl;
2299 memcpy(dst,src,imsize);
2304 for (ii=1;ii<4;ii++) {
2305 for (jj=1;jj<4;jj++) {
2306 int x = (int)(ii*dim[0] / 4);
2307 int y = (int)(jj*dim[1] / 4);
2308 std::cout << cur->GetScalarComponentAsFloat(x,y,0,0)
2310 << out->GetScalarComponentAsFloat(x,y,slice,0)
2323 std::vector<DicomNode*>::iterator it;
2324 for (it=im.begin(); it!=im.end(); ++it)
2326 vtkImageData* out = vtkImageData::New();
2327 out->ShallowCopy(mReader.GetImage((*it)->ImageGetFullFileName()));
2333 //================================================================
2336 //================================================================
2337 void WxGimmick::GetSelectedDicomNodes(std::vector<DicomNode*>& f)
2339 wxArrayTreeItemIds id;
2340 // TO DO : TEST THAT STYLE IS MULTIPLE
2341 unsigned int nb = mTreeListCtrl->GetSelections(id);
2343 for (unsigned int i=0; i<nb; ++i)
2345 TreeItemData *data =
2346 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2347 if ((data) && (data->IsDicomNode()))
2349 f.push_back ( data->GetDicomNode() );
2353 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2355 f.push_back ( data->GetDicomNode() ); //->ImageGetFullFileName() );
2357 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2359 DicomNode::ChildrenListType::iterator j;
2360 for (j =data->GetDicomNode()->GetChildrenList().begin();
2361 j!=data->GetDicomNode()->GetChildrenList().end();
2364 f.push_back((*j)); //->ImageGetFullFileName() ); }
2370 //================================================================
2372 //================================================================
2373 void WxGimmick::GetSelectedItems(std::vector<wxTreeItemId>& f)
2375 wxArrayTreeItemIds id;
2376 // TO DO : TEST THAT STYLE IS MULTIPLE
2377 unsigned int nb = mTreeListCtrl->GetSelections(id);
2379 for (unsigned int i=0; i<nb; ++i)
2384 //================================================================
2386 //================================================================
2387 DicomNode* WxGimmick::GetDicomNodeOfItem(const wxTreeItemId& i)
2389 TreeItemData *data =
2390 (TreeItemData *)mTreeListCtrl->GetItemData(i);
2391 if (data) return ( data->GetDicomNode() );
2394 //================================================================
2396 //================================================================
2397 //================================================================
2398 //================================================================
2399 //================================================================
2415 //================================================================
2416 //================================================================
2417 //================================================================
2418 //================================================================
2420 BEGIN_EVENT_TABLE(WxGimmick, wxPanel)
2422 EVT_MENU(PopUp_NewCollection,WxGimmick::OnPopUpNewCollection)
2423 EVT_MENU(PopUp_OpenCollection,WxGimmick::OnPopUpOpenCollection)
2424 EVT_MENU(PopUp_CloseCollection,WxGimmick::OnPopUpCloseCollection)
2425 EVT_MENU(PopUp_DeleteCollection,WxGimmick::OnPopUpDeleteCollection)
2426 EVT_MENU(PopUp_AddFile, WxGimmick::OnPopUpAddFile)
2427 EVT_MENU(PopUp_AddRawFile, WxGimmick::OnPopUpAddRawFile)
2428 EVT_MENU(PopUp_AddDirectory, WxGimmick::OnPopUpAddDirectory)
2429 EVT_MENU(PopUp_Remove, WxGimmick::OnPopUpRemove)
2430 EVT_MENU(PopUp_About, WxGimmick::OnPopUpAbout)
2431 EVT_MENU(PopUp_Settings, WxGimmick::OnPopUpSettings)
2433 EVT_MENU_RANGE(PopUp_Sort, PopUp_Sort+99, WxGimmick::OnPopUpSort)
2434 EVT_MENU_RANGE(PopUp_User, PopUp_User+99, WxGimmick::OnPopUpUser)
2439 EVT_TREE_BEGIN_DRAG(TreeListCtrlId, WxGimmick::OnBeginDrag)
2440 EVT_TREE_BEGIN_RDRAG(TreeListCtrlId, WxGimmick::OnBeginRDrag)
2441 EVT_TREE_END_DRAG(TreeListCtrlId, WxGimmick::OnEndDrag)
2444 EVT_TREE_BEGIN_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnBeginLabelEdit)
2445 EVT_TREE_END_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnEndLabelEdit)
2448 EVT_TREE_DELETE_ITEM(TreeListCtrlId, WxGimmick::OnDeleteItem)
2449 #if 0 // there are so many of those that logging them causes flicker
2450 EVT_TREE_GET_INFO(TreeListCtrlId, WxGimmick::OnGetInfo)
2453 EVT_TREE_SET_INFO(TreeListCtrlId, WxGimmick::OnSetInfo)
2456 EVT_TREE_ITEM_EXPANDED(TreeListCtrlId, WxGimmick::OnItemExpanded)
2457 EVT_TREE_ITEM_EXPANDING(TreeListCtrlId, WxGimmick::OnItemExpanding)
2458 EVT_TREE_ITEM_COLLAPSED(TreeListCtrlId, WxGimmick::OnItemCollapsed)
2459 EVT_TREE_ITEM_COLLAPSING(TreeListCtrlId, WxGimmick::OnItemCollapsing)
2462 EVT_TREE_SEL_CHANGED(TreeListCtrlId, WxGimmick::OnSelChanged)
2463 EVT_TREE_SEL_CHANGING(TreeListCtrlId, WxGimmick::OnSelChanging)
2465 EVT_TREE_KEY_DOWN(TreeListCtrlId, WxGimmick::OnTreeKeyDown)
2466 // ACTIVATION = DOUBLE CLICK OR ENTER ON SELECTED
2467 EVT_TREE_ITEM_ACTIVATED(TreeListCtrlId, WxGimmick::OnItemActivated)
2469 // so many differents ways to handle right mouse button clicks...
2470 // EVT_CONTEXT_MENU(WxGimmick::OnContextMenu)
2471 // EVT_TREE_ITEM_MENU is the preferred event for creating context menus
2472 // on a tree control, because it includes the point of the click or item,
2473 // meaning that no additional placement calculations are required.
2474 // EVT_TREE_ITEM_MENU(TreeListCtrlId, WxGimmick::OnItemMenu)
2476 EVT_TREE_ITEM_RIGHT_CLICK(TreeListCtrlId, WxGimmick::OnItemRightClick)
2479 // EVT_RIGHT_DOWN(WxGimmick::OnRMouseDown)
2480 // EVT_RIGHT_UP(WxGimmick::OnRMouseUp)
2481 // EVT_RIGHT_DCLICK(WxGimmick::OnRMouseDClick)
2484 //IMPLEMENT_DYNAMIC_CLASS(WxGimmick, wxTreeListCtrl)
2487 wxTree::wxTree(wxWindow *parent, const wxWindowID id,
2488 const wxPoint& pos, const wxSize& size,
2490 : wxTreeListCtrl(parent, id, pos, size, style)
2492 m_reverseSort = false;
2496 // Add some items to the tree
2497 AddTestItemsToTree(5, 2);
2503 #if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
2504 void WxGimmick::CreateButtonsImageList(int size)
2509 mTreeListCtrl->SetButtonsImageList(NULL);
2513 // Make an image list containing small icons
2514 wxImageList *images = new wxImageList(size, size, true);
2516 // should correspond to TreeListCtrlIcon_xxx enum
2519 icons[0] = wxIcon(icon3_xpm); // closed
2520 icons[1] = wxIcon(icon3_xpm); // closed, selected
2521 icons[2] = wxIcon(icon5_xpm); // open
2522 icons[3] = wxIcon(icon5_xpm); // open, selected
2524 for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
2526 int sizeOrig = icons[i].GetWidth();
2527 if ( size == sizeOrig )
2529 images->Add(icons[i]);
2533 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
2537 mTreeListCtrl->AssignButtonsImageList(images);
2540 void WxGimmick::CreateButtonsImageList(int WXUNUSED(size))
2546 int WxGimmick::OnCompareItems(const wxTreeItemId& item1,
2547 const wxTreeItemId& item2)
2549 if ( m_reverseSort )
2551 // just exchange 1st and 2nd items
2552 return mTreeListCtrl->OnCompareItems(item2, item1);
2556 return mTreeListCtrl->OnCompareItems(item1, item2);
2561 void WxGimmick::DoToggleIcon(const wxTreeItemId& item)
2564 int image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_Folder)
2567 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Normal);
2569 image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_FolderSelected)
2570 ? TreeIcon_FileSelected
2571 : TreeIcon_FolderSelected;
2572 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Selected);
2575 void WxGimmick::LogEvent(const wxChar *name, const wxTreeEvent& event)
2577 wxTreeItemId item = event.GetItem();
2580 text << _T('"') << mTreeListCtrl->GetItemText(item).c_str() << _T('"');
2582 text = _T("invalid item");
2583 // wxLogMessage(wxT("%s(%s)"), name, text.c_str());
2588 #define TREE_EVENT_HANDLER(name) \
2589 void WxGimmick::name(wxTreeEvent& event) \
2591 /* LogEvent(_T(#name), event); */ \
2592 /* SetLastItem(mTreeListCtrl->wxTreeItemId()) *;*/ \
2596 TREE_EVENT_HANDLER(OnBeginRDrag)
2597 TREE_EVENT_HANDLER(OnDeleteItem)
2598 TREE_EVENT_HANDLER(OnGetInfo)
2599 TREE_EVENT_HANDLER(OnSetInfo)
2600 //TREE_EVENT_HANDLER(OnItemExpanded)
2601 TREE_EVENT_HANDLER(OnItemExpanding)
2602 //TREE_EVENT_HANDLER(OnItemCollapsed)
2603 //TREE_EVENT_HANDLER(OnSelChanged)
2604 // TREE_EVENT_HANDLER(OnSelChanging)
2607 void WxGimmick::OnItemCollapsed(wxTreeEvent& event)
2609 // std::cout << "* Collapsed *"<<std::endl;
2612 #undef TREE_EVENT_HANDLER
2614 void WxGimmick::OnTreeKeyDown(wxTreeEvent& event)
2617 // LogKeyEvent(wxT("Tree key down "), event.GetKeyEvent());
2618 std::cout << "* Key down *"<<std::endl;
2619 if (event.GetKeyCode()==WXK_RIGHT)
2621 std::cout << "Right"<<std::endl;
2622 wxTreeItemId itemId = mTreeListCtrl->GetSelection();
2625 std::cout << "item is ok"<<std::endl;
2626 wxPoint clientpt = event.GetPoint();
2627 wxPoint screenpt = ClientToScreen(clientpt);
2628 ShowMenu(itemId, clientpt);
2633 std::cout << "NOT Right"<<std::endl;
2638 void WxGimmick::OnBeginDrag(wxTreeEvent& event)
2640 wxTreeItemId id = event.GetItem();
2641 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2642 // std::cout << "OnBeginDrag("<<id<<")"<<std::endl;
2643 if (data->IsDatabase())
2645 // std::cout << "-- IS ROOT"<<std::endl;
2648 else if (data->IsDicomNode())
2650 // std::cout << "-- IS NODE"<<std::endl;
2653 // need to explicitly allow drag
2654 if ( event.GetItem() != GetDatabaseItem() )
2656 m_draggedItem = event.GetItem();
2658 wxPoint clientpt = event.GetPoint();
2659 wxPoint screenpt = ClientToScreen(clientpt);
2661 wxLogMessage(wxT("OnBeginDrag: started dragging %s at screen coords (%i,%i)"),
2662 GetItemText(m_draggedItem).c_str(),
2663 screenpt.x, screenpt.y);
2669 wxLogMessage(wxT("OnBeginDrag: this item can't be dragged."));
2674 void WxGimmick::OnEndDrag(wxTreeEvent& event)
2676 wxTreeItemId id = event.GetItem();
2677 // std::cout << "OnEndDrag("<<id<<")"<<std::endl;
2678 if (!id.IsOk()) return;
2679 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2680 if (data->IsDatabase())
2682 // std::cout << "-- IS ROOT"<<std::endl;
2684 else if (data->IsDicomNode())
2686 // std::cout << "-- IS NODE"<<std::endl;
2690 wxTreeItemId itemSrc = m_draggedItem,
2691 itemDst = event.GetItem();
2692 m_draggedItem = (wxTreeItemId)0l;
2694 // where to copy the item?
2695 if ( itemDst.IsOk() && !ItemHasChildren(itemDst) )
2697 // copy to the parent then
2698 itemDst = GetItemParent(itemDst);
2701 if ( !itemDst.IsOk() )
2703 wxLogMessage(wxT("OnEndDrag: can't drop here."));
2708 wxString text = GetItemText(itemSrc);
2709 wxLogMessage(wxT("OnEndDrag: '%s' copied to '%s'."),
2710 text.c_str(), GetItemText(itemDst).c_str());
2712 // just do append here - we could also insert it just before/after the item
2713 // on which it was dropped, but this requires slightly more work... we also
2714 // completely ignore the client data and icon of the old item but could
2715 // copy them as well.
2717 // Finally, we only copy one item here but we might copy the entire tree if
2718 // we were dragging a folder.
2719 int image = wxGetApp().ShowImages() ? TreeIcon_File : -1;
2720 AppendItem(itemDst, text, image);
2725 //====================================================================
2726 void WxGimmick::OnBeginLabelEdit(wxTreeEvent& event)
2728 // std::cout << "OnBeginLabelEdit"<<std::endl;
2729 wxTreeItemId id = event.GetItem();
2730 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2731 // If not a root : veto
2732 if (data->IsDatabase())
2739 //====================================================================
2741 //====================================================================
2742 void WxGimmick::OnEndLabelEdit(wxTreeEvent& event)
2744 // std::cout << "OnEndLabelEdit"<<std::endl;
2745 wxTreeItemId id = event.GetItem();
2746 TreeItemData *data = GetItemData(id);
2747 // If not a database : bug !
2748 if (data->IsDatabase())
2750 data->GetDicomNode()->GetDicomDatabase()->SetName(wx2std(event.GetLabel()));
2751 mFieldsView->UpdateValues(data->GetDicomNode());
2755 std::cerr<< "!!!! Internal error : send bug report !!!!"<<std::endl;
2758 //====================================================================
2761 void WxGimmick::OnItemCollapsing(wxTreeEvent& event)
2763 // wxLogMessage(wxT("OnItemCollapsing"));
2765 // for testing, prevent the user from collapsing the first child folder
2766 wxTreeItemId itemId = event.GetItem();
2769 if ( IsTestItem(itemId) )
2771 wxMessageBox(wxT("You can't collapse this item."));
2779 //====================================================================
2780 void WxGimmick::ShowHelp()
2785 mHelpWindow = new WxGimmickHelpWindow(this);
2787 mHelpWindow->CenterOnParent();
2788 mHelpWindow->ShowModal();
2791 //====================================================================
2797 //================================================================
2798 //================================================================
2799 //================================================================
2800 //================================================================
2801 //================================================================
2803 //================================================================
2804 //================================================================
2805 //================================================================
2806 //================================================================
2807 //================================================================
2813 // ----------------------------------------------------------------------------
2815 // ----------------------------------------------------------------------------
2817 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_DRAG)
2818 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_RDRAG)
2819 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_DELETE_ITEM)
2820 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_GET_INFO)
2821 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SET_INFO)
2822 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDED)
2823 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDING)
2824 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSED)
2825 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSING)
2828 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT)
2829 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_LABEL_EDIT)
2832 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED)
2833 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGING)
2834 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_KEY_DOWN)
2835 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU)
2836 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_ITEM_STYLE_CHANGED)
2838 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_ACTIVATED)
2839 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK)
2840 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK)
2841 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_DRAG)
2842 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK)
2843 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP)
2844 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MENU)
2846 // ----------------------------------------------------------------------------
2848 // ----------------------------------------------------------------------------
2850 IMPLEMENT_ABSTRACT_CLASS(WxGimmickEvent, wxNotifyEvent)
2853 WxGimmickEvent::WxGimmickEvent(wxEventType commandType,
2855 const wxTreeItemId& item)
2857 wxNotifyEvent(commandType, tree->GetId()),
2861 // m_editCancelled = false;
2863 SetEventObject(tree);
2866 SetClientObject(tree->mTreeListCtrl->GetItemData(item));
2869 WxGimmickEvent::WxGimmickEvent(wxEventType commandType, int id)
2871 wxNotifyEvent(commandType, id),
2875 // m_editCancelled = false;
2878 WxGimmickEvent::WxGimmickEvent(const WxGimmickEvent & event)
2880 wxNotifyEvent(event),
2884 m_evtKey = event.m_evtKey;
2885 m_item = event.m_item;
2886 m_itemOld = event.m_itemOld;
2887 mColor = event.mColor;
2888 mUserData = event.mUserData;
2889 // m_pointDrag = event.m_pointDrag;
2890 // m_label = event.m_label;
2891 // m_editCancelled = event.m_editCancelled;
2901 //================================================================
2902 //================================================================
2903 //================================================================
2904 //================================================================
2905 //================================================================
2906 WxGimmickFrame::WxGimmickFrame( wxWindow *parent,
2909 : wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size)
2911 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
2912 mWxGimmick = new WxGimmick(this,-1,
2915 sizer->Add(mWxGimmick,1,wxGROW);
2917 SetAutoLayout(true);
2920 //================================================================
2922 //================================================================
2923 WxGimmickFrame::~WxGimmickFrame()
2926 //================================================================
2928 //================================================================
2929 void WxGimmickFrame::OnSelChanged(WxGimmickEvent& event)
2931 // std::cout << "+++++ WxGimmickFrame::OnSelChanged ++++++++++"
2933 std::vector<std::string> file;
2934 // mWxGimmick->GetSelectedImages(file);
2936 std::vector<std::string>::iterator i;
2937 for (i=file.begin();i!=file.end();++i)
2939 std::cout << "'" << *i << "'" << std::endl;
2941 std::cout << "++++++++++++++++++++" << std::endl;
2944 //================================================================
2946 //================================================================
2947 BEGIN_EVENT_TABLE(WxGimmickFrame, wxFrame)
2948 EVT_TREEVIEWLIST_SEL_CHANGED(-1,WxGimmickFrame::OnSelChanged)
2950 //================================================================