2 #include <creaImageIOWxGimmick.h>
3 #include <creaImageIODicomNodeComparators.h>
5 #include <creaMessageManager.h>
7 #include "icons/database.xpm"
8 #include "icons/folder.xpm"
9 #include "icons/dicomdir.xpm"
10 #include "icons/patient.xpm"
11 #include "icons/study.xpm"
12 #include "icons/series.xpm"
13 #include "icons/image.xpm"
14 #include "icons/root.xpm"
15 #include <wx/filedlg.h>
16 #include <wx/dirdlg.h>
19 #include <vtkCamera.h>
20 #include <vtkRenderer.h>
22 #include <wx/filefn.h>
23 //#include <wx/tipwin.h>
27 #include <boost/filesystem.hpp>
28 #include <boost/algorithm/string.hpp>
32 //================================================================
33 const int WxGimmick::UserMenuFirstId = 1000;
34 //================================================================
36 //================================================================
49 //================================================================
51 //================================================================
54 PopUp_NewCollection = 100,
55 PopUp_OpenCollection = 101,
56 PopUp_CloseCollection = 102,
57 PopUp_DeleteCollection = 103,
58 PopUp_AddDirectory = 110,
60 PopUp_AddRawFile = 112,
65 PopUp_User = WxGimmick::UserMenuFirstId,
67 PopUp_AddToFavorites = 702
69 //================================================================
71 //================================================================
72 #define TreeListCtrlId 10000
73 //================================================================
75 //================================================================
76 const icon_id Icon[5] = { Icon_Database,
81 //================================================================
84 //================================================================
85 class WxGimmickDicomNodeData : public DicomNodeData
88 WxGimmickDicomNodeData
89 (WxGimmickTreeItemData* d = 0) :
93 ~WxGimmickDicomNodeData();
95 WxGimmickTreeItemData* GetTreeItemData()
96 { return mTreeItemData; }
97 void SetTreeItemData( WxGimmickTreeItemData* d)
98 { mTreeItemData = d; }
99 inline bool IsLoaded() { return mLoaded; }
100 inline void SetLoaded(bool v) { mLoaded = v; }
103 WxGimmickTreeItemData* mTreeItemData;
106 //================================================================
109 //================================================================
110 class WxGimmickTreeItemData : public wxTreeItemData
113 WxGimmickTreeItemData(DicomNode* node)
123 WxGimmickDicomNodeData* data =
124 node->GetData<WxGimmickDicomNodeData*>();
127 if (data->GetTreeItemData()!=0)
129 std::cout << "WxGimmickTreeItemData ERROR ****"
133 data->SetTreeItemData(this);
136 node->SetData( new WxGimmickDicomNodeData(this) );
137 if (node->GetType()==DicomNode::Database)
147 ~WxGimmickTreeItemData()
151 WxGimmickDicomNodeData* data =
152 mDicomNode->GetData<WxGimmickDicomNodeData*>();
153 if (data) data->SetTreeItemData(0);
157 inline void ResetDicomNode()
162 inline void SetItemId ( const wxTreeItemId& item ) { mItemId = item; }
163 inline const wxTreeItemId& GetItemId() const { return mItemId; }
165 inline bool IsDefault() const { return (mType == 0); }
166 inline bool IsDatabase() const { return (mType == 2); }
167 inline bool IsDicomNode() const { return (mType == 1); }
169 inline DicomNode* GetDicomNode() { return mDicomNode; }
170 inline long& UpdateTime() { return mUpdateTime; }
171 inline bool IsLoaded()
173 mDicomNode->GetData<WxGimmickDicomNodeData*>()->IsLoaded();
175 inline void SetLoaded(bool v)
177 mDicomNode->GetData<WxGimmickDicomNodeData*>()->SetLoaded(v);
180 inline int GetUserFlags() const { return mUserFlags; }
181 inline void SetUserFlags(int f) { mUserFlags = f; }
184 // The type of item :
187 // 2 = DicomNode of type Database
189 wxTreeItemId mItemId;
190 DicomNode* mDicomNode;
195 //================================================================
198 //================================================================
199 WxGimmickDicomNodeData::~WxGimmickDicomNodeData()
203 mTreeItemData->ResetDicomNode();
206 //================================================================
241 //================================================================
242 //================================================================
243 //================================================================
244 //================================================================
245 //================================================================
246 //================================================================
247 //================================================================
248 WxGimmick::WxGimmick(wxWindow *parent,
254 : wxPanel(parent,id,pos,size),
255 mSelectionType(image_type),
256 mSaveConfigurationOnClose(true),
259 // Initialize image size corresponding to current selection
260 switch (mSelectionType)
262 case GIMMICK_2D_IMAGE_SELECTION : mSelectionMaxImageDimension = 2; break;
263 case GIMMICK_3D_IMAGE_SELECTION : mSelectionMaxImageDimension = 3; break;
264 case GIMMICK_4D_IMAGE_SELECTION : mSelectionMaxImageDimension = 4; break;
265 default : mSelectionMaxImageDimension = 0;
269 // Start the threads ...
273 SetDatabaseExtension("sqlite3");
274 // Create the UserSettings dir if does not exist
275 CreateUserSettingsDirectory();
276 // Sets the current directory to the Setting dir
277 mCurrentDirectory = std2wx(GetUserSettingsDirectory());
279 // Window layout creation
280 wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
283 mSplitter1 = new wxSplitterWindow( this, -1);
285 // TreeCtrl on the left
290 //| wxTR_LINES_AT_ROOT
291 | wxTR_FULL_ROW_HIGHLIGHT
298 | wxTR_EDIT_LABELS //Use this style if you wish the user to be able to edit labels in the tree list control.
299 //wxTR_NO_BUTTONS For convenience to document that no buttons are to be drawn.
300 | wxTR_HAS_BUTTONS //Use this style to show + and - buttons to the left of parent items.
301 | wxTR_TWIST_BUTTONS //Use this style to show Mac-style twister buttons to the left of parent items. If both wxTR_HAS_BUTTONS and wxTR_TWIST_BUTTONS are given, twister buttons are generated.
302 //wxTR_NO_LINES Use this style to hide vertical level connectors.
303 | wxTR_FULL_ROW_HIGHLIGHT //Use this style to have the background colour and the selection highlight extend over the entire horizontal row of the tree list control window. (This flag is ignored under Windows unless you specify wxTR_NO_LINES as well.)
304 | wxTR_LINES_AT_ROOT //Use this style to show lines between root nodes. Only applicable if wxTR_HIDE_ROOT is set and wxTR_NO_LINES is not set.
305 | wxTR_HIDE_ROOT //Use this style to suppress the display of the root node, effectively causing the first-level nodes to appear as a series of root nodes.
306 // wxTR_ROW_LINES // Use this style to draw a contrasting border between displayed rows.
307 // wxTR_HAS_VARIABLE_ROW_HEIGHT// Use this style to cause row heights to be just big enough to fit the content. If not set, all rows use the largest row height. The default is that this flag is unset.
308 // wxTR_SINGLE For convenience to document that only one item may be selected at a time. Selecting another item causes the current selection, if any, to be deselected. This is the default.
309 | wxTR_MULTIPLE // Use this style to allow a range of items to be selected. If a second range is selected, the current range, if any, is deselected.
310 | wxTR_EXTENDED // Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases.)
311 //wxTR_DEFAULT_STYLE The set of flags that are closest to the defaults for the native control for a particular toolkit.
312 //| wxTR_VIRTUAL //The application provides items text on demand.
315 mTreeListCtrl = new wxTreeListCtrl(mSplitter1,
321 mTreeListCtrl->SetIndent(0);
322 mTreeListCtrl->SetLineSpacing(5);
327 wxPanel *rpanel = new wxPanel( mSplitter1, -1 );
329 wxBoxSizer *rsizer = new wxBoxSizer(wxHORIZONTAL);
330 // Right panel top/bottom split
331 mSplitter2 = new wxSplitterWindow( rpanel , -1);
334 mPanelImage = new wxPanel(mSplitter2,-1);
335 mPanelImage->SetBackgroundColour( wxColour(0,0,0) );
337 wxBoxSizer *isizer = new wxBoxSizer(wxHORIZONTAL );
338 mPanelImage->SetSizer( isizer );
341 mwxNotebook = new wxNotebook(mSplitter2,
342 -1,wxDefaultPosition, wxDefaultSize, 0);
346 // Fields view (bottom)
347 mFieldsView = new WxGimmickFieldsView(mwxNotebook,-1,
351 mFieldsView->SetColors
352 ( GetSettings().Colour(DicomNode::Database),
353 GetSettings().BgColour(DicomNode::Database),
354 GetSettings().Colour(DicomNode::Patient),
355 GetSettings().BgColour(DicomNode::Patient),
356 GetSettings().Colour(DicomNode::Study),
357 GetSettings().BgColour(DicomNode::Study),
358 GetSettings().Colour(DicomNode::Series),
359 GetSettings().BgColour(DicomNode::Series),
360 GetSettings().Colour(DicomNode::Image),
361 GetSettings().BgColour(DicomNode::Image));
362 mwxNotebook->AddPage( mFieldsView, _T("Dicom fields"));
365 mHelp = new WxGimmickHelp(mwxNotebook);
366 mwxNotebook->AddPage( mHelp, _T("Help"));
369 int wsize = size.GetWidth();
370 int hsize = size.GetHeight();
371 int previewhsize = 150;
372 int previewwsize = 400;
374 mSplitter2->SetMinimumPaneSize( previewhsize );
375 mSplitter2->SplitHorizontally( mPanelImage, mwxNotebook, //mFieldsView,
376 hsize - previewhsize);
378 rsizer->Add( mSplitter2,1,wxGROW ,0);
380 rpanel->SetAutoLayout(true);
381 rpanel->SetSizer( rsizer );
385 mInteractor = new crea::creawxVTKRenderWindowInteractor(mPanelImage,-1);
386 mInteractor->UseCaptureMouseOn();
388 mViewer = vtkImageViewer2::New();
389 mViewer->SetupInteractor ( mInteractor );
390 mViewer->SetInput(mReader.GetImage(""));
392 isizer-> Add( mInteractor ,1,wxGROW ,0);
394 topsizer->Add( mSplitter1,1,wxGROW ,0);
397 mSplitter1->SetMinimumPaneSize( 200 );
398 mSplitter1->SplitVertically(mTreeListCtrl,
400 wsize - previewwsize );
403 // ProcessImageEvents();
404 SetSizer( topsizer );
407 mDatabaseListFile = GetUserSettingsDirectory();
408 mDatabaseListFile += "collections.txt";
413 ShowImage(mReader.GetImage(""));
415 // Show help if no collection
416 if (GetDicomDatabaseList().size()==0)
418 mwxNotebook->SetSelection(1);
422 mwxNotebook->SetSelection(0);
424 // mJustStarted = true;
426 //================================================================
430 #define VALID_FILE_SEPARATOR "\\"
431 #define INVALID_FILE_SEPARATOR "/"
433 #define INVALID_FILE_SEPARATOR "\\"
434 #define VALID_FILE_SEPARATOR "/"
437 //================================================================
438 const std::string& WxGimmick::GetUserSettingsDirectory()
440 if (mUserSettingsDirectory.size()==0)
442 #if defined(__GNUC__)
443 mUserSettingsDirectory = getenv("HOME");
444 #elif defined(_WIN32)
445 mUserSettingsDirectory = getenv("USERPROFILE");
447 mUserSettingsDirectory += "/.gimmick/";
448 boost::algorithm::replace_all( mUserSettingsDirectory,
449 INVALID_FILE_SEPARATOR ,
450 VALID_FILE_SEPARATOR);
452 return mUserSettingsDirectory;
454 //================================================================
456 //========================================================================
457 void WxGimmick::CreateUserSettingsDirectory()
459 if (! boost::filesystem::is_directory( GetUserSettingsDirectory() ) )
461 creaMessage("Gimmick!",1,"==> Directory '"<<GetUserSettingsDirectory()<<"' "
462 << "does not exist : creating it"<<std::endl);
464 if ( ! boost::filesystem::create_directory( GetUserSettingsDirectory() ) )
466 creaMessage("Gimmick!",1,"!! ERROR CREATING '"<<GetUserSettingsDirectory()<<"'");
470 //========================================================================
472 //================================================================
473 WxGimmick::~WxGimmick()
475 // std::cout << "WxGimmick::~WxGimmick()" <<std::endl;
476 if (mSaveConfigurationOnClose) SaveConfiguration();
479 // std::cout << "Reader stopped"<<std::endl;
481 DicomDatabaseListType::iterator i;
482 for (i =GetDicomDatabaseList().begin();
483 i!=GetDicomDatabaseList().end();
491 //================================================================
494 //================================================================
495 void WxGimmick::RebuildView()
499 mTreeListCtrl->DeleteRoot(); //DeleteAllItems();
500 // mTreeDefaultItemId = wxTreeItemId();
503 int nbattr = mSettings.GetMaxNumberOfColumns();
505 for (int j=0;j<nbattr; j++)
507 mTreeListCtrl->AddColumn (_T(""),
508 200, //DEFAULT_COL_WIDTH,
514 mTreeListCtrl->SetMainColumn (0);
515 mTreeListCtrl->SetColumnEditable (0, true);
517 mTreeRootId = mTreeListCtrl->AddRoot( _T(""),Icon_Root,Icon_Root);
519 // The collections columns legends
520 mCollectionsTitlesItemId =
521 CreateChildrenColumnsTitles(mTreeRootId,DicomNode::Database);
523 DicomDatabaseListType::iterator i;
524 for (i =GetDicomDatabaseList().begin();
525 i!=GetDicomDatabaseList().end();
528 UpdateDicomDatabaseView(*i);
531 mTreeListCtrl->Expand(mTreeRootId);
533 // mTreeListCtrl->ExpandAll(mTreeRootId);
534 // std::cout << "EO RebuildAll"<<std::endl;
536 //================================================================
540 //================================================================
541 void WxGimmick::UpdateDicomDatabaseView(DicomDatabase* db)
547 // Does the db exist ?
548 wxTreeItemIdValue cookie;
549 for (dbid = mTreeListCtrl->GetFirstChild(mTreeRootId,cookie);
551 dbid = mTreeListCtrl->GetNextChild(mTreeRootId,cookie))
553 data = (TreeItemData *)mTreeListCtrl->GetItemData(dbid);
554 if ((data->IsDatabase())&&(data->GetDicomNode()==db)) break;
557 // Not found : create
561 int iconid = Icon[DicomNode::Database];
564 // std::cout << " -> Creating item for '"<<db->GetLabel()<<"'"<<std::endl;
565 data = new TreeItemData(db);
566 dbid = mTreeListCtrl->AppendItem( mTreeRootId,
567 std2wx(db->GetLabel()),
571 data->SetItemId(dbid);
572 mTreeListCtrl->SetItemTextColour
573 (dbid,mSettings.Colour(DicomNode::Database));
574 mTreeListCtrl->SetItemBackgroundColour
575 (dbid,mSettings.BgColour(DicomNode::Database));
577 // The patients columns legends
578 CreateChildrenColumnsTitles(dbid,DicomNode::Patient);
581 // Increase UpdateTime to detect obsolete items after
583 data->UpdateTime()++;
585 DicomNode::ChildrenListType::iterator j;
586 for (j= db->GetChildrenList().begin();
587 j!=db->GetChildrenList().end();
590 UpdateDicomNodeView(*j,dbid);
593 DeleteObsoleteChildren(dbid);
595 mTreeListCtrl->EnsureVisible(dbid);
598 //================================================================
600 //================================================================
601 void WxGimmick::UpdateDicomNodeView(DicomNode* n,
602 const wxTreeItemId& parent)
606 // std::cout << "* UpdateDicomNodeView("<<n->GetLabel()<<")"<<std::endl;
608 wxTreeItemId newparent = parent;
611 if ((!mSettings.MergeStudySeries()) ||
612 (n->GetType() != DicomNode::Study))
614 // Does the item exist ?
615 wxTreeItemIdValue cookie;
616 for (newparent = mTreeListCtrl->GetFirstChild(parent,cookie);
618 newparent = mTreeListCtrl->GetNextChild(parent,cookie))
620 data = (TreeItemData *)mTreeListCtrl->GetItemData(newparent);
621 if (data->GetDicomNode() == n) break;
623 // Not found : create
624 if (!newparent.IsOk())
626 int image(Icon[n->GetType()]);
627 wxColour *colour(&mSettings.Colour(n->GetType()));
628 wxColour *bgcolour(&mSettings.BgColour(n->GetType()));
630 if (n->GetType()==DicomNode::Image)
632 // std::cout << "!!!Image"<<std::endl;
633 if (n->GetData<NodeData*>()!=0)
635 // std::cout << ">> n->GetData<NodeData*>()!=0" << std::endl;
636 if (n->GetData<NodeData*>()->IsLoaded())
638 colour = &mSettings.LoadedImageColour();
640 // std::cout << "<< n->GetData<NodeData*>()!=0" << std::endl;
644 data = new TreeItemData(n);
645 newparent = mTreeListCtrl->AppendItem(parent,
649 data->SetItemId(newparent);
650 mTreeListCtrl->SetItemTextColour(newparent,*colour);
651 mTreeListCtrl->SetItemBackgroundColour(newparent,*bgcolour);
653 UpdateColumns(newparent);
656 if (n->GetType()!=DicomNode::Image)
658 CreateChildrenColumnsTitles(newparent,n->GetType()+1);
664 UpdateColumns(newparent,true);
667 // synchonise update time with parent
668 TreeItemData * parent_data =
669 (TreeItemData *)mTreeListCtrl->GetItemData(parent);
670 data->UpdateTime() = parent_data->UpdateTime();
673 DicomNode::ChildrenListType::iterator i;
674 for (i=n->GetChildrenList().begin();
675 i!=n->GetChildrenList().end();
678 UpdateDicomNodeView(*i,newparent);
681 if (n->GetType() != DicomNode::Image)
682 DeleteObsoleteChildren(newparent);
685 //================================================================
687 //================================================================
688 void WxGimmick::UpdateColumns(wxTreeItemId& item,
692 (TreeItemData *)mTreeListCtrl->GetItemData(item);
693 DicomNode* node = data->GetDicomNode();
697 // Update only the first field (for #children update)
698 DicomNode* node2 = node;
699 // If Study and Series level are merged and node type is Series
700 // then have to get back to the Study level
701 if ((mSettings.MergeStudySeries())&&
702 (node->GetType() == DicomNode::Series))
703 node2 = node->GetParent();
706 lab += node2->GetFieldValueMap()
707 [ mSettings.GetColumnList(node2->GetType())[0].Key ];
709 if (node->GetType() != DicomNode::Image)
711 if (node->GetChildrenList().size()>0)
714 sprintf(sz," [%d]",node->GetNumberOfChildren());
718 mTreeListCtrl->SetItemText(item,std2wx(lab));
723 Settings::ColumnListType::iterator col;
724 // If Study and Series level are merged and node type is Series
725 // then have to fill the Study level cols first
726 if ((mSettings.MergeStudySeries())&&
727 (node->GetType() == DicomNode::Series))
729 DicomNode* node2 = node->GetParent();
730 for (col = mSettings.GetColumnList(node2->GetType()).begin();
731 col != mSettings.GetColumnList(node2->GetType()).end();
734 std::string s = node2->GetFieldValueMap()[col->Key];
739 sprintf(sz," [%d]",node->GetNumberOfChildren());
742 mTreeListCtrl->SetItemText (item, c, std2wx(s));
747 for (col = mSettings.GetColumnList(node->GetType()).begin();
748 col != mSettings.GetColumnList(node->GetType()).end();
751 std::string s = node->GetFieldValueMap()[col->Key];
752 if ((c==0)&&(node->GetType() != DicomNode::Image))
755 sprintf(sz," [%d]",node->GetNumberOfChildren());
758 mTreeListCtrl->SetItemText (item, c, std2wx(s));
764 //================================================================
766 //================================================================
767 wxTreeItemId WxGimmick::CreateChildrenColumnsTitles
771 // Creates the sub-level columns titles
773 = new TreeItemData(0);
774 wxTreeItemId id = mTreeListCtrl->AppendItem( item,
780 mTreeListCtrl->SetItemFont(id, *wxITALIC_FONT);
781 mTreeListCtrl->SetItemTextColour(id, mSettings.Colour(t));
782 mTreeListCtrl->SetItemBackgroundColour(id, mSettings.BgColour(t));
783 UpdateColumnsTitles(id,t);
786 //================================================================
788 //================================================================
789 void WxGimmick::UpdateColumnsTitles(wxTreeItemId& item,
792 // std::cout << "Update columns titles "<<t<<std::endl;
794 Settings::ColumnListType::iterator col;
795 for (col = mSettings.GetColumnList(t).begin();
796 col != mSettings.GetColumnList(t).end();
799 // std::cout << col->Name << std::endl;
800 mTreeListCtrl->SetItemText (item, c, std2wx(col->Name));
804 //================================================================
807 //================================================================
808 void WxGimmick::DeleteObsoleteChildren(wxTreeItemId& id)
811 TreeItemData * parent_data =
812 (TreeItemData *)mTreeListCtrl->GetItemData(id);
815 wxTreeItemIdValue cookie;
816 std::vector<wxTreeItemId> children;
817 for (child = mTreeListCtrl->GetFirstChild(id,cookie);
819 child = mTreeListCtrl->GetNextChild(id,cookie))
821 children.push_back(child);
823 std::vector<wxTreeItemId>::iterator i;
824 for (i=children.begin();i!=children.end();++i)
827 (TreeItemData *)mTreeListCtrl->GetItemData(*i);
829 ((data->GetDicomNode()>0) &&
830 ((data->UpdateTime() != parent_data->UpdateTime()))) ||
831 ((data->IsDicomNode()) &&
832 (data->GetDicomNode()==0))
835 // std::cout << "DOBSC="<<mTreeListCtrl->GetItemText(*i)<<std::endl;
836 mTreeListCtrl->Delete(*i);
840 //================================================================
842 //================================================================
843 void WxGimmick::OpenOrNewDatabase(bool open)
847 long style = wxFD_SAVE | wxFD_OVERWRITE_PROMPT;
848 if (open) style = wxOPEN | wxFILE_MUST_EXIST;
849 std::string wc("*.");
850 wc += GetDatabaseExtension();
852 // TO DO : Handler give their wildcards
853 wxFileDialog* FD = new wxFileDialog( 0,
861 if (FD->ShowModal()!=wxID_OK) return;
863 std::string filename = wx2std (FD->GetPath());
864 mCurrentDirectory = FD->GetDirectory();
868 boost::filesystem::path filepath(filename);
869 boost::filesystem::change_extension(filepath,GetDatabaseExtension());
870 if ( boost::filesystem::exists(filepath) )
872 boost::filesystem::remove(filepath);
874 LG : works on Linux but not Windows :
875 if ( ! boost::filesystem::remove(filepath) )
877 wxMessageBox(_T("Could not overwrite ")
878 +std2wx(filepath.string()),
889 DicomDatabase* db = new DicomDatabase(filename);
896 wxMessageBox(_T("An error occured while opening ")
906 wxGetTextFromUser(_T("Enter collection name"),_T("New collection"),
908 db->SetName(wx2std(collname));
913 wxMessageBox(_T("An error occured while creating ")
921 if (GetDicomDatabaseList().size()==0) mFieldsView->UpdateFields(db);
922 GetDicomDatabaseList().push_back(db);
923 UpdateDicomDatabaseView(db);
927 //================================================================
930 //================================================================
931 void WxGimmick::LoadConfiguration()
934 // std::cout << "WxGimmick : Reading config"<<std::endl;
935 LoadOrCreateFavoritesDatabase();
938 creaMessage("Gimmick!",1,"Gimmick! : ==> Loading collections from '"<<mDatabaseListFile<<"'"<<std::endl);
943 s.open(mDatabaseListFile.c_str());
950 if (str.size()==0) continue;
952 std::vector<std::string> tokens;
953 boost::split( tokens, str, boost::is_any_of("\t") );
955 DicomDatabase* db = new DicomDatabase(tokens[0]);
957 // std::cout << " -> Loading collection '"<<tokens[0]<<"'"<<std::endl;
959 if (tokens.size()==2)
961 db->SetName(tokens[1]);
966 GetDicomDatabaseList().push_back(db);
967 db->DBLoadChildren(db,DicomNode::Patient);
968 if (mSettings.HasActiveComparator(DicomNode::Patient))
971 ( mSettings.GetActiveComparator(DicomNode::Patient) );
976 creaMessage("Gimmick!",1," ==> ERROR opening collection '"<<tokens[0]<<"'"<<std::endl);
984 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).");
988 mTreeListCtrl->SetBackgroundColour(mSettings.BgColour(DicomNode::Database));
989 if (GetDicomDatabaseList().begin() !=
990 GetDicomDatabaseList().end() )
992 mFieldsView->UpdateFields(*GetDicomDatabaseList().begin());
998 //================================================================
1000 //================================================================
1001 void WxGimmick::SaveConfiguration()
1004 creaMessage("Gimmick!",1,"Gimmick! : Saving configuration..."<<std::endl);
1006 creaMessage("Gimmick!",1,"Gimmick! : ==> Saving collections in '"
1007 <<mDatabaseListFile<<"'"<<std::endl);
1010 s.open(mDatabaseListFile.c_str());
1013 creaError("Gimmick! : error opening '"<<mDatabaseListFile<<"'");
1016 DicomDatabaseListType::iterator i;
1017 for (i =GetDicomDatabaseList().begin();
1018 i!=GetDicomDatabaseList().end();
1021 s << (*i)->GetFileName() << "\t";
1022 s << (*i)->GetName() << std::endl;
1028 //================================================================
1030 //================================================================
1031 void WxGimmick::LoadOrCreateFavoritesDatabase()
1035 //================================================================
1038 //================================================================
1039 void WxGimmick::OnClose(wxCloseEvent& event)
1041 if (mSaveConfigurationOnClose) SaveConfiguration();
1043 //================================================================
1045 //================================================================
1046 void WxGimmick::OnItemActivated(wxTreeEvent& event)
1052 // std::cout << "OnItemActivated" <<std::endl;
1053 wxTreeItemId itemId = event.GetItem();
1054 if (mTreeListCtrl->IsExpanded(itemId))
1056 mTreeListCtrl->Collapse(itemId);
1060 mTreeListCtrl->Expand(itemId);
1063 //================================================================
1065 //================================================================
1066 void WxGimmick::LoadChildren(wxTreeItemId& id)
1068 TreeItemData *item = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1071 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1072 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1075 // If children not already loaded : do it
1077 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1078 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1081 // Some new children loaded
1083 if (mSettings.HasActiveComparator
1084 (item->GetDicomNode()->GetType()+1))
1086 /* std::cout << "Sorting using '"
1087 << mSettings.GetActiveComparator
1088 (item->GetDicomNode()->GetType()+1).GetName()
1091 item->GetDicomNode()->SortChildren
1092 ( mSettings.GetActiveComparator
1093 (item->GetDicomNode()->GetType()+1)
1095 // std::cout << "ok"<<std::endl;
1098 DicomNode::ChildrenListType::iterator i;
1099 for (i=item->GetDicomNode()->GetChildrenList().begin();
1100 i!=item->GetDicomNode()->GetChildrenList().end();
1103 UpdateDicomNodeView(*i,id);
1106 // EO If children not already loaded
1110 //================================================================
1113 //================================================================
1114 void WxGimmick::OnItemExpanded(wxTreeEvent& event)
1116 // std::cout << "* Expanded *"<<std::endl;
1121 wxTreeItemId itemId = event.GetItem();
1122 LoadChildren(itemId);
1126 // expand if collapsed and collapse if expanded ...
1127 TreeItemData *item =
1128 (TreeItemData *)mTreeListCtrl->GetItemData(itemId);
1131 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1132 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1135 // If children not already loaded : do it
1137 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1138 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1142 // Some new children loaded
1144 if (mSettings.HasActiveComparator
1145 (item->GetDicomNode()->GetType()+1))
1147 /* std::cout << "Sorting using '"
1148 << mSettings.GetActiveComparator
1149 (item->GetDicomNode()->GetType()+1).GetName()
1152 item->GetDicomNode()->SortChildren
1153 ( mSettings.GetActiveComparator
1154 (item->GetDicomNode()->GetType()+1)
1156 // std::cout << "ok"<<std::endl;
1159 // If images : sort them
1160 if (item->IsDicomNode())
1162 if (item->GetDicomNode()->GetType()==DicomNode::Series)
1166 LexicographicalDicomNodeComparator compare;
1167 // DicomNodeImageImageNumberComparator c1;
1169 DicomNodeImageSliceLocationComparator c1;
1170 DicomNodeImageImageNumberComparator c2;
1171 DicomNodeImageFileNameComparator cn;
1175 // std::cout << "SORT"<<std::endl;
1176 item->GetDicomNode()->SortChildren(compare);
1177 // std::cout << "EO SORT"<<std::endl;
1185 DicomNode::ChildrenListType::iterator i;
1186 for (i=item->GetDicomNode()->GetChildrenList().begin();
1187 i!=item->GetDicomNode()->GetChildrenList().end();
1190 UpdateDicomNodeView(*i,itemId);
1193 // EO If children not already loaded
1196 // mTreeListCtrl->Expand(itemId);
1199 //================================================================
1203 //=====================================================================
1204 void WxGimmick::InsertRoot(wxTreeItemId& id, Root* r)
1207 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1212 data->GetDicomNode()->GetDicomDatabase()->LoadAll();
1213 printf(">>>>>> Time to load all = %ldms \n",sw.Time());
1215 UpdateRootView(data->GetDicomNode()->GetDicomDatabase());
1218 if (data->IsDicomNode())
1221 r->Insert(data->GetDicomNode());
1222 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1225 else if (data->IsDatabase())
1228 DicomNode::ChildrenListType::iterator j;
1229 for (j= data->GetDicomNode()->GetChildrenList().begin();
1230 j!=data->GetDicomNode()->GetChildrenList().end();
1235 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1241 //=====================================================================
1245 //=================================================
1246 void WxGimmick::DeleteDicomDatabase(wxTreeItemId& id,
1250 DicomDatabaseListType::iterator i = find(GetDicomDatabaseList().begin(),
1251 GetDicomDatabaseList().end(),
1254 GetDicomDatabaseList().erase(i);
1255 mTreeListCtrl->Delete(id);
1257 //=================================================
1261 //=====================================================================
1263 void WxGimmick::OnItemRightClick(wxTreeEvent& event)
1265 wxTreeItemId itemId = event.GetItem();
1268 wxPoint clientpt = event.GetPoint();
1269 wxPoint screenpt = ClientToScreen(clientpt);
1270 ShowMenu(itemId, clientpt);
1274 //=====================================================================
1276 //=====================================================================
1277 void WxGimmick::ShowMenu(wxTreeItemId id, const wxPoint& pt)
1280 // std::cout << "ShowMenu" <<std::endl;
1282 TreeItemData *data =
1283 (TreeItemData *)mTreeListCtrl->GetItemData(id);
1289 title << wxT("Menu for ") << mTreeListCtrl->GetItemText(id);
1293 title = wxT("Menu for no particular item");
1300 if (id==mCollectionsTitlesItemId)
1302 menu.Append(PopUp_NewCollection, _T("&New collection"));
1303 menu.Append(PopUp_OpenCollection, _T("&Open collection"));
1307 if (data->IsDatabase())
1309 wxMenu* addmenu = new wxMenu;
1310 addmenu->Append(PopUp_AddDirectory, _T("Scan &Directory"));
1311 addmenu->Append(PopUp_AddFile, _T("Select &File(s)"));
1312 // addmenu->Append(PopUp_AddRawFile, _T("Add &Raw image"));
1313 menu.AppendSubMenu(addmenu, _T("&Add image(s) to collection..."));
1314 menu.Append(PopUp_CloseCollection, _T("&Close collection"));
1315 menu.Append(PopUp_DeleteCollection, _T("&Delete collection"));
1317 if (data->IsDicomNode())
1322 std::string str("&Remove ");
1323 str += data->GetDicomNode()->GetTypeName();
1324 menu.Append(PopUp_Remove, std2wx(str));
1328 if ((data->GetDicomNode()>0)&&
1329 ( data->GetDicomNode()->GetType()<DicomNode::Image))
1331 int ctype = data->GetDicomNode()->GetType()+1;
1332 if (mSettings.HasActiveComparator(ctype))
1334 wxMenu* sortmenu = new wxMenu;
1336 Settings::ComparatorsList::iterator i;
1337 for (i =mSettings.GetComparatorsList(ctype).begin();
1338 i !=mSettings.GetComparatorsList(ctype).end();
1341 sortmenu->AppendRadioItem(PopUp_Sort+n, std2wx(i->GetName()));
1345 sortmenu->Check(PopUp_Sort+
1346 mSettings.GetActiveComparatorIndex(ctype)
1349 std::string sortmenustr("&Sort ");
1350 sortmenustr += DicomNode::GetPluralTypeName(ctype);
1351 sortmenustr += " by...";
1352 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1353 menu.AppendSubMenu(sortmenu,std2wx(sortmenustr));
1356 item->GetDicomNode()->SortChildren
1357 ( mSettings.GetActiveComparator
1358 (item->GetDicomNode()->GetType()+1)
1360 std::cout << "ok"<<std::endl;
1365 // Event : user can customize the menu
1367 ev(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU,this,id);
1371 ev.SetDicomNode(data->GetDicomNode());
1373 GetEventHandler()->ProcessEvent(ev);
1376 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1377 menu.Append(PopUp_Settings, wxT("&Settings..."));
1378 menu.Append(PopUp_About, wxT("&About..."));
1381 wxMenu* newmenu = new wxMenu;
1382 wxMenu* openmenu = new wxMenu;
1383 Tree::RootHandlerListType::iterator h;
1385 for (h= Tree::GetRootHandlerList().begin();
1386 h!=Tree::GetRootHandlerList().end();
1389 if ((*h)->SupportsNew())
1391 newmenu->Append(PopUp_New+i, std2wx((*h)->GetName()));
1393 if ((*h)->SupportsOpen())
1394 openmenu->Append(PopUp_Open+i, std2wx((*h)->GetName()));
1398 menu.AppendSubMenu(openmenu, _T("&Open"));
1399 menu.AppendSubMenu(newmenu, _T("&New"));
1403 if ((data->IsDatabase())||(data->IsDicomNode()))
1405 Root* itroot = data->GetDicomNode()->GetDicomDatabase();
1406 // if (!itroot) itroot = data->GetDicomNode()->GetRoot();
1407 wxMenu* insertmenu = new wxMenu;
1408 bool hasone = false;
1410 Tree::RootListType::iterator j;
1411 for (j = mTree->GetDatabaseList().begin();
1412 j != mTree->GetDatabaseList().end();
1415 // std::cout << (*j)->GetName() << " "
1416 // << (*j)->GetTypeName()
1417 // << " i="<<(*j)->SupportsInsert()<<std::endl;
1418 if ( ((*j)!=itroot) && ((*j)->SupportsInsert()) )
1420 insertmenu->Append(PopUp_Insert+i,
1421 std2wx((*j)->GetName()));
1427 if (hasone) menu.AppendSubMenu(insertmenu, _T("&Insert into"));
1429 if (data->IsDatabase())
1431 menu.Append(PopUp_Close, wxT("&Close"));
1433 if (data->IsDicomNode() && data->GetDicomNode()->GetDicomDatabase()->SupportsRemove())
1435 menu.Append(PopUp_Remove, wxT("&Remove"));
1440 PopupMenu(&menu, pt);
1441 #endif // wxUSE_MENUS
1443 // std::cout << "EO ShowMenu" <<std::endl;
1445 //=====================================================================
1447 //=====================================================================
1448 // Pop up menu callbacks
1449 void WxGimmick::OnPopUpAbout(wxCommandEvent& event)
1451 wxMessageBox( _T("Give me my medical images quick ! \n\n (c) CREATIS-LRMN 2008\n laurent.guigues@creatis.insa-lyon.fr"),
1453 wxOK | wxICON_INFORMATION, this);
1455 //=====================================================================
1457 //=====================================================================
1458 void WxGimmick::OnPopUpSettings(wxCommandEvent& event)
1460 WxGimmickSettingsDialog* s =
1461 new WxGimmickSettingsDialog(this,&mSettings);
1465 //=====================================================================
1467 //=====================================================================
1468 void WxGimmick::OnPopUpNewCollection(wxCommandEvent& event)
1471 OpenOrNewDatabase(false);
1473 //=====================================================================
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;
1507 // std::cout << "OnPopUpClose"<<std::endl;
1508 // wxTreeItemId id = event.GetId();
1509 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1510 DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
1512 wxRemoveFile(std2wx(r->GetFileName()));
1513 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1514 DeleteDicomDatabase(mItemOfMenu,r);
1517 //=====================================================================
1519 void DisplayUpdateSummary( DicomDatabase::UpdateSummary& summary,
1522 std::stringstream mess;
1523 mess << "Dirs\tscanned\t\t\t: " << summary.scanned_dirs << "\n";
1524 mess << "Files\tscanned\t\t\t: " << summary.scanned_files << "\n";
1525 mess << "Files\thandled\t\t\t: " << summary.handled_images << "\n\n";
1526 mess << "Patients\tadded\t\t: " << summary.added_patients<< "\n";
1527 mess << "Studies\tadded\t\t: " << summary.added_studies<< "\n";
1528 mess << "Series\tadded\t\t: " << summary.added_series<< "\n";
1529 mess << "Images\tadded\t\t: " << summary.added_images<< "\n\n";
1531 sprintf(times,"Time to parse dir \t\t: %ld ms \t%d°/o\nTime to read files info \t: %ld ms \t%d°/o\nTime to update structs \t: %ld ms \t%d°/o\nTime to update database \t: %ld ms \t%d°/o\nTotal time \t\t\t: %ld ms",
1533 (int)( summary.parse_time*100./summary.total_time),
1534 summary.file_scan_time,
1535 (int)(summary.file_scan_time*100./summary.total_time),
1536 summary.update_structs_time,
1537 (int)(summary.update_structs_time*100./summary.total_time),
1538 summary.update_database_time,
1539 (int)(summary.update_database_time*100./summary.total_time),
1540 summary.total_time );
1544 wxMessageBox(std2wx(mess.str()),_T("Update summary"),wxOK,parent);
1548 //=====================================================================
1549 void WxGimmick::OnPopUpAddFile(wxCommandEvent& event)
1551 long style = wxOPEN | wxFILE_MUST_EXIST | wxFD_MULTIPLE;
1552 std::string wc("*");
1553 wxFileDialog* FD = new wxFileDialog( 0,
1561 if (FD->ShowModal()==wxID_OK)
1565 mCurrentDirectory = FD->GetDirectory();
1566 wxArrayString files;
1567 FD->GetPaths(files);
1569 std::vector<std::string> filenames;
1570 for (i=0;i<files.GetCount();++i)
1571 filenames.push_back(wx2std(files[i]));
1574 TreeItemData *data =
1576 mTreeListCtrl->GetItemData(mItemOfMenu);
1577 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1578 DicomDatabase::UpdateSummary summary;
1579 wxProgressDialog* progress =
1580 new wxProgressDialog(_T("Adding file(s)"),
1585 wxPD_ESTIMATED_TIME |
1586 wxPD_REMAINING_TIME |
1589 db->AddFiles(filenames,progress,summary);
1591 progress->Pulse(_T("Updating view..."));
1592 UpdateDicomDatabaseView(db);
1594 DisplayUpdateSummary(summary,this);
1598 //=====================================================================
1600 //=====================================================================
1601 void WxGimmick::OnPopUpAddRawFile(wxCommandEvent& event)
1603 wxMessageBox(_T("Not yet implemented !"),_T("Sorry"),wxOK,this);
1605 //=====================================================================
1607 //=====================================================================
1608 void WxGimmick::OnPopUpAddDirectory(wxCommandEvent& event)
1610 long style = wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST;
1613 _T("Select directory"),
1617 if (FD->ShowModal()==wxID_OK)
1620 bool recurse = false;
1621 if (wxMessageBox(_T("Recurse into sub-directories ?"),
1622 _T("Scan directory"),
1623 wxYES_NO,this ) == wxYES)
1629 wxProgressDialog* progress =
1630 new wxProgressDialog(_T("Scanning directory"),
1631 _T("Parsing directory"),
1635 wxPD_ESTIMATED_TIME |
1636 wxPD_REMAINING_TIME |
1638 DicomDatabase::UpdateSummary summary;
1640 std::string dirname = wx2std (FD->GetPath()) ;
1641 mCurrentDirectory = FD->GetPath();
1642 TreeItemData *data =
1644 mTreeListCtrl->GetItemData(mItemOfMenu);
1645 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1646 db->AddDirectory(dirname,recurse,progress,summary);
1648 progress->Pulse(_T("Updating view..."));
1649 UpdateDicomDatabaseView(db);
1652 DisplayUpdateSummary(summary,this);
1654 if (summary.cancelled_by_user)
1656 std::cout << "!! Cancelled by user !!"<<std::endl;
1662 //=====================================================================
1664 //=====================================================================
1665 void WxGimmick::OnPopUpRemove(wxCommandEvent& event)
1669 wxMessageBox(_T("Not yet implemented"),_T("Sorry !"),wxOK);
1673 // wxTreeItemId id = event.GetId();
1674 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1676 std::string mess("Remove ");
1677 mess += data->GetDicomNode()->GetTypeName();
1678 mess += " from collection ?";
1679 int answer = wxMessageBox(std2wx(mess), _T("Confirm"), wxYES_NO);
1680 if (answer == wxNO) return;
1682 if ( mTreeListCtrl->IsSelected(mItemOfMenu) )
1684 wxTreeItemId next = mTreeListCtrl->GetNextSibling(mItemOfMenu);
1687 mTreeListCtrl->SelectItem(next);
1695 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1696 db->Remove(data->GetDicomNode());
1697 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1698 // TODO : Optimize update only parent's branch
1699 UpdateDicomDatabaseView(db);
1700 // DeleteDicomDatabase(mItemOfMenu,r);
1702 //=====================================================================
1704 //=====================================================================
1705 void WxGimmick::OnPopUpSort(wxCommandEvent& event)
1708 // std::cout << "OnPopUpSort"<<std::endl;
1709 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1710 int index = event.GetId() - PopUp_Sort;
1711 DicomNode* node = data->GetDicomNode();
1712 DicomNode::Type ctype = node->GetType()+1;
1713 mSettings.SetActiveComparatorIndex(ctype,index);
1715 if (node->ChildrenLoaded())
1718 mTreeListCtrl->DeleteChildren(mItemOfMenu);
1720 /* std::cout << "Sorting using '"
1721 << mSettings.GetActiveComparator(ctype).GetName()
1724 node->SortChildren ( mSettings.GetActiveComparator(ctype) );
1725 // std::cout << "ok"<<std::endl;
1729 CreateChildrenColumnsTitles(mItemOfMenu,ctype);
1730 DicomNode::ChildrenListType::iterator i;
1731 for (i=node->GetChildrenList().begin();
1732 i!=node->GetChildrenList().end();
1735 UpdateDicomNodeView(*i,mItemOfMenu);
1739 //=====================================================================
1742 //=====================================================================
1743 void WxGimmick::OnPopUpUser(wxCommandEvent& event)
1745 // std::cout << "OnPopUpUser"<<std::endl;
1748 //=====================================================================
1750 //=================================================
1751 void WxGimmick::CreateImageList(int size)
1755 mTreeListCtrl->SetImageList(NULL);
1764 // should correspond to Icon_xxx enum
1765 icons[Icon_Patient] = wxIcon(patient_xpm);
1766 icons[Icon_Study] = wxIcon(study_xpm);
1767 icons[Icon_Series] = wxIcon(series_xpm);
1768 icons[Icon_Image] = wxIcon(image_xpm);
1769 icons[Icon_Database] = wxIcon(database_xpm);
1770 icons[Icon_Folder] = wxIcon(folder_xpm);
1771 icons[Icon_DicomDir] = wxIcon(dicomdir_xpm);
1772 icons[Icon_Root] = wxIcon(root_xpm);
1775 // mFirstRootIconIndex = 8;
1778 Tree::RootHandlerListType::iterator h;
1780 for (h= Tree::GetDatabaseHandlerList().begin();
1781 h!=Tree::GetDatabaseHandlerList().end();
1784 icons[mFirstRootIconIndex+i] = (*h)->GetIcon();
1788 unsigned int NbIcons = 8;//mFirstRootIconIndex + i;
1789 // Make an image list containing small icons
1790 wxImageList *images = new wxImageList(size, size, true);
1792 int sizeOrig = icons[0].GetWidth();
1793 for ( size_t i = 0; i < NbIcons; i++ )
1795 if ( size == sizeOrig )
1797 images->Add(icons[i]);
1801 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
1804 mTreeListCtrl->AssignImageList(images);
1806 //=================================================
1815 //================================================================
1816 bool WxGimmick::IsImageSelectable(DicomNode* node)
1818 int rows = node->ImageGetRows();
1819 int cols = node->ImageGetColumns();
1820 int frms = node->ImageGetFrames();
1822 // std::cout << "R/C/F = " << rows << "/"<< cols <<"/"<<frms<<std::endl;
1826 else if (cols>0) dim=2;
1827 else if (rows>0) dim=1;
1831 std::cout << "Unknown image dimension : cannot select !"
1835 else if (dim>mSelectionMaxImageDimension)
1837 std::cout << "Selecting "<<dim<<"D images is not allowed !"
1842 if ( mTreeListCtrl->GetSelectionSize() == 0 )
1844 mCurrentSelectionImageSize[0] = cols;
1845 mCurrentSelectionImageSize[1] = rows;
1846 mCurrentSelectionImageSize[2] = frms;
1851 if ( dim == mSelectionMaxImageDimension )
1853 std::cout << "Cannot add this image to selection : would result in a "<<dim+1<<"D image !" << std::endl;
1856 if ( ( cols != mCurrentSelectionImageSize[0] ) ||
1857 ( rows != mCurrentSelectionImageSize[1] ) ||
1858 ( frms != mCurrentSelectionImageSize[2] ) )
1860 std::cout << "Cannot add this image to selection : image size is incomptatible with currently selected images" << std::endl;
1864 // std::cout << "Selecting : "<<node->ImageGetFullFileName() << std::endl;
1867 //================================================================
1869 //================================================================
1870 void WxGimmick::OnSelChanging(wxTreeEvent& event)
1873 wxTreeItemId id = event.GetItem();
1876 std::cout << "INTERNAL ERROR : ID NOT OK"<<std::endl;
1881 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1882 if (data->IsDicomNode())
1884 if (data->GetDicomNode()>0)
1886 // An image was selected
1887 if (data->GetDicomNode()->GetType()==DicomNode::Image)
1889 if (IsImageSelectable(data->GetDicomNode())) event.Allow();
1891 // A series was selected
1892 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
1894 // If images not loaded do it
1896 // can be selected if all its images can
1898 wxTreeItemIdValue cookie;
1899 for (child = mTreeListCtrl->GetFirstChild(id,cookie);
1901 child = mTreeListCtrl->GetNextChild(id,cookie))
1903 TreeItemData *cdata =
1904 (TreeItemData *)mTreeListCtrl->GetItemData(child);
1905 if ((cdata->IsDicomNode())&&
1906 (cdata->GetDicomNode()>0)&&
1907 (cdata->GetDicomNode()->GetType()==DicomNode::Image)&&
1908 (!IsImageSelectable(cdata->GetDicomNode())))
1916 //================================================================
1918 //================================================================
1919 void WxGimmick::OnSelChanged(wxTreeEvent& event)
1921 // wxBusyCursor busy;
1922 // std::vector<wxTreeItemId> items;
1923 // GetSelectedItems(items);
1925 std::vector<DicomNode*>::iterator i;
1926 for (i=nodes.begin();i!=nodes.end();++i)
1928 std::cout << "'" << (*i)->GetFieldValue("FullFileName")
1929 << "'" << std::endl;
1931 std::cout << "++++++++++++++++++++" << std::endl;
1933 // ShowImage(mReader.GetImage(""));
1935 bool no_image = true;
1937 static int max = 1000;
1940 // if (items.size()>0)
1943 // Update image preview : send requests to the MTImageReader
1944 // bool first = true;
1945 // std::vector<wxTreeItemId>::iterator i;
1946 // for (i=items.begin();i!=items.end();++i)
1952 DicomNode* node = GetDicomNodeOfItem(items[0]);
1954 // Update dicom fields panel
1955 mFieldsView->UpdateValues(node);
1959 wxTreeItemId item = mTreeListCtrl->GetCurrent();
1961 DicomNode* n = GetDicomNodeOfItem(item);
1963 if (n) mFieldsView->UpdateValues(n);
1966 (n->GetType()==DicomNode::Image) )
1971 //if (i==items.begin())
1972 mCurImageItemToShow = item;
1974 int maxprio = mReader.GetMaximalPriority();
1975 int prio = maxprio + 1000;
1976 wxTreeItemId sib = item; //GetTreeListCtrl()->GetNextSibling(*i);
1979 DicomNode* nsib = GetDicomNodeOfItem(sib);
1982 // std::cout << "-- Request '"
1983 // << nsib->GetFieldValue("FullFileName")
1984 // << "' prio="<<prio<<std::endl;
1985 mReader.Request(this,
1986 nsib->ImageGetFullFileName(),
1988 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
1992 sib = GetTreeListCtrl()->GetNextSibling(sib);
1994 prio = maxprio + 999;
1995 sib = GetTreeListCtrl()->GetPrevSibling(item);
1998 DicomNode* nsib = GetDicomNodeOfItem(sib);
2001 // std::cout << "-- Request '"
2002 // << nsib->GetFieldValue("FullFileName")
2003 // << "' prio="<<prio<<std::endl;
2004 mReader.Request(this,
2005 nsib->ImageGetFullFileName(),
2007 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
2011 sib = GetTreeListCtrl()->GetPrevSibling(sib);
2013 // mImageFileNameToNode[n->GetFieldValue("FullFileName")] = n;
2016 ProcessImageEvents();
2018 // std::cout << "* Selection changed * (im)"<<std::endl;
2020 //---------------------------------------------------------------------
2022 WxGimmickEvent ev(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED,
2026 GetEventHandler()->ProcessEvent(ev);
2028 if (no_image) ShowImage(mReader.GetImage(""));
2031 //================================================================
2033 //================================================================
2034 void WxGimmick::ShowImage(vtkImageData* im)
2036 // wxBusyCursor busy;
2037 mViewer->SetInput( im );
2038 mViewer->SetSlice( 0 );
2041 int x1,x2,y1,y2,z1,z2;
2044 im->GetSpacing(spx,spy,spz);
2045 im->GetExtent (x1,x2,y1,y2,z1,z2);
2047 std::cout << "-----------------------------"<<std::endl;
2048 std::cout << x1 << "-"<<x2<<std::endl;
2049 std::cout << y1 << "-"<<y2<<std::endl;
2050 std::cout << z1 << "-"<<z2<<std::endl;
2051 std::cout << spx << "-"<<spy<<"-"<<spz<<std::endl;
2075 double *range = im->GetScalarRange();
2076 mViewer->SetColorWindow(range[1] - range[0]);
2077 mViewer->SetColorLevel(0.5 * (range[1] + range[0]));
2079 mViewer->GetRenderer()->ResetCamera();
2083 mViewer->GetRenderer()->ComputeVisiblePropBounds(bounds);
2086 std::cout <<"bounds : "<<bounds[0]<<","
2091 <<bounds[5]<<std::endl;
2093 mViewer->GetRenderer()->ResetCameraClippingRange(bounds);
2095 vtkCamera *camera = mViewer->GetRenderer()->GetActiveCamera();
2097 camera->SetViewUp ( spx*0, -spy*1, spz*0);
2098 camera->SetPosition( spx*(x1+x2)/2, spy*(y1+y2)/2, spz*10000000);
2099 camera->SetFocalPoint ( spx*(x1+x2)/2 , spy*(y1+y2)/2 , spz*0);
2101 camera->ComputeViewPlaneNormal();
2102 camera->SetParallelScale( spx*(x2-x1)/2.0 );
2104 camera->Roll ( 180 );
2108 mInteractor->Render();
2110 //================================================================
2117 //================================================================
2119 OnMultiThreadImageReaderEvent(const std::string& filename,
2120 MultiThreadImageReaderUser::EventType e,
2121 vtkImageData* image)
2123 if (filename.size()==0)
2125 mImageEventQueue.push_back(ImageEventType(image));
2128 std::map<std::string,DicomNode*>::iterator i;
2129 i = mImageFileNameToNode.find(filename);
2130 if (i!=mImageFileNameToNode.end())
2132 wxTreeItemId id = i->second->GetData<NodeData*>()->GetTreeItemData()->GetItemId();
2133 mImageEventQueue.push_back(ImageEventType(id,image));
2136 //================================================================
2138 //================================================================
2139 // Processes the queue of image events
2140 void WxGimmick::ProcessImageEvents()
2142 // std::cout << "++++++++++ ProcessImageEvents " << std::endl;
2143 MultiThreadImageReaderEventLock();
2146 while (!mImageEventQueue.empty())
2148 ImageEventType e = mImageEventQueue.front();
2149 mImageEventQueue.pop_front();
2154 mTreeListCtrl->SetItemTextColour(e.item,
2155 mSettings.LoadedImageColour());//wxImageLoadedColour);
2156 TreeItemData *data =
2157 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2158 data->SetLoaded(true);
2160 if (mCurImageItemToShow == e.item)
2165 else if (!mCurImageItemToShow.IsOk())
2170 else if (e.item.IsOk())
2172 mTreeListCtrl->SetItemTextColour(e.item,mSettings.Colour(DicomNode::Image)); //.wxImageUnloadedColour);
2173 TreeItemData *data =
2174 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2175 data->SetLoaded(false);
2178 mImageEventQueue.clear();
2179 MultiThreadImageReaderEventUnlock();
2180 // std::cout << "++++++++++ END ProcessImageEvents " << std::endl;
2182 //================================================================
2184 //================================================================
2185 void WxGimmick::OnInternalIdle()
2187 ProcessImageEvents();
2192 mJustStarted = false;
2197 //================================================================
2200 //================================================================
2201 // LG : For the moment any selection is valid but in the future
2202 // incomplete selections can be invalid...
2203 bool WxGimmick::IsSelectionValid()
2205 return (mTreeListCtrl->GetSelectionSize()>0);
2207 //================================================================
2209 //================================================================
2210 void WxGimmick::GetSelectedFiles(std::vector<std::string>& f)
2212 wxArrayTreeItemIds id;
2213 // TO DO : TEST THAT STYLE IS MULTIPLE
2214 unsigned int nb = mTreeListCtrl->GetSelections(id);
2216 for (unsigned int i=0; i<nb; ++i)
2218 TreeItemData *data =
2219 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2220 if ((data) && (data->IsDicomNode()))
2222 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2224 f.push_back ( data->GetDicomNode()->ImageGetFullFileName() );
2226 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2228 DicomNode::ChildrenListType::iterator j;
2229 for (j =data->GetDicomNode()->GetChildrenList().begin();
2230 j!=data->GetDicomNode()->GetChildrenList().end();
2233 f.push_back((*j)->ImageGetFullFileName());
2239 //================================================================
2241 //================================================================
2242 void WxGimmick::GetSelectedImages(std::vector<vtkImageData*>& f)
2244 wxArrayTreeItemIds id;
2245 // TO DO : TEST THAT STYLE IS MULTIPLE
2246 unsigned int nb = mTreeListCtrl->GetSelections(id);
2249 // Collect the brute vector of Image nodes
2250 std::vector<DicomNode*> im;
2251 for (unsigned int i=0; i<nb; ++i)
2253 TreeItemData *data =
2254 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2255 if ((data) && (data->IsDicomNode()))
2257 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2259 im.push_back ( data->GetDicomNode() );
2262 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2264 DicomNode::ChildrenListType::iterator j;
2265 for (j =data->GetDicomNode()->GetChildrenList().begin();
2266 j!=data->GetDicomNode()->GetChildrenList().end();
2269 im.push_back ( *j );
2274 // Create the output data
2277 // Only one image : give it
2278 vtkImageData* out = vtkImageData::New();
2279 out->ShallowCopy(mReader.GetImage(im.front()->ImageGetFullFileName()));
2282 else if (im.size()>1)
2284 vtkImageData* first = mReader.GetImage( im.front()->ImageGetFullFileName() );
2285 if (first->GetDataDimension()==2)
2288 vtkImageData* out = vtkImageData::New();
2289 out->CopyStructure(first);
2290 out->SetScalarType(first->GetScalarType());
2292 first->GetExtent(ext);
2294 out->SetExtent(ext);
2295 // LG : TODO : Z Spacing ?
2297 // ==> to get an accurate ZSpacing from a Dicom set of files
2298 // ==> you need a gdcm::SerieHelper
2301 out->AllocateScalars();
2303 //first->Print(std::cout);
2304 // out->Print(std::cout);
2307 first->GetDimensions(dim);
2308 unsigned long imsize =
2309 ( (unsigned long)first->GetScalarPointer(0,1,0)
2310 - (unsigned long)first->GetScalarPointer(0,0,0))
2314 std::vector<DicomNode*>::iterator it;
2315 for (it=im.begin(); it!=im.end(); ++it)
2317 //std::cout << "copying slice "<<slice <<std::endl;
2318 vtkImageData* cur = mReader.GetImage( (*it)->ImageGetFullFileName() );
2320 void* src = cur->GetScalarPointer(0,0,0);
2321 void* dst = out->GetScalarPointer(0,0,slice);
2322 // std::cout << "src="<<src<<std::endl;
2323 // std::cout << "dst="<<dst<<std::endl;
2324 // std::cout << "siz="<<imsize<<std::endl;
2325 memcpy(dst,src,imsize);
2330 for (ii=1;ii<4;ii++) {
2331 for (jj=1;jj<4;jj++) {
2332 int x = (int)(ii*dim[0] / 4);
2333 int y = (int)(jj*dim[1] / 4);
2334 std::cout << cur->GetScalarComponentAsFloat(x,y,0,0)
2336 << out->GetScalarComponentAsFloat(x,y,slice,0)
2349 std::vector<DicomNode*>::iterator it;
2350 for (it=im.begin(); it!=im.end(); ++it)
2352 vtkImageData* out = vtkImageData::New();
2353 out->ShallowCopy(mReader.GetImage((*it)->ImageGetFullFileName()));
2359 //================================================================
2362 //================================================================
2363 void WxGimmick::GetSelectedDicomNodes(std::vector<DicomNode*>& f)
2365 wxArrayTreeItemIds id;
2366 // TO DO : TEST THAT STYLE IS MULTIPLE
2367 unsigned int nb = mTreeListCtrl->GetSelections(id);
2369 for (unsigned int i=0; i<nb; ++i)
2371 TreeItemData *data =
2372 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2373 if ((data) && (data->IsDicomNode()))
2375 f.push_back ( data->GetDicomNode() );
2379 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2381 f.push_back ( data->GetDicomNode() ); //->ImageGetFullFileName() );
2383 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2385 DicomNode::ChildrenListType::iterator j;
2386 for (j =data->GetDicomNode()->GetChildrenList().begin();
2387 j!=data->GetDicomNode()->GetChildrenList().end();
2390 f.push_back((*j)); //->ImageGetFullFileName() ); }
2396 //================================================================
2398 //================================================================
2399 void WxGimmick::GetSelectedItems(std::vector<wxTreeItemId>& f)
2401 wxArrayTreeItemIds id;
2402 // TO DO : TEST THAT STYLE IS MULTIPLE
2403 unsigned int nb = mTreeListCtrl->GetSelections(id);
2405 for (unsigned int i=0; i<nb; ++i)
2410 //================================================================
2412 //================================================================
2413 DicomNode* WxGimmick::GetDicomNodeOfItem(const wxTreeItemId& i)
2415 TreeItemData *data =
2416 (TreeItemData *)mTreeListCtrl->GetItemData(i);
2417 if (data) return ( data->GetDicomNode() );
2420 //================================================================
2422 //================================================================
2423 //================================================================
2424 //================================================================
2425 //================================================================
2441 //================================================================
2442 //================================================================
2443 //================================================================
2444 //================================================================
2446 BEGIN_EVENT_TABLE(WxGimmick, wxPanel)
2448 EVT_MENU(PopUp_NewCollection,WxGimmick::OnPopUpNewCollection)
2449 EVT_MENU(PopUp_OpenCollection,WxGimmick::OnPopUpOpenCollection)
2450 EVT_MENU(PopUp_CloseCollection,WxGimmick::OnPopUpCloseCollection)
2451 EVT_MENU(PopUp_DeleteCollection,WxGimmick::OnPopUpDeleteCollection)
2452 EVT_MENU(PopUp_AddFile, WxGimmick::OnPopUpAddFile)
2453 EVT_MENU(PopUp_AddRawFile, WxGimmick::OnPopUpAddRawFile)
2454 EVT_MENU(PopUp_AddDirectory, WxGimmick::OnPopUpAddDirectory)
2455 EVT_MENU(PopUp_Remove, WxGimmick::OnPopUpRemove)
2456 EVT_MENU(PopUp_About, WxGimmick::OnPopUpAbout)
2457 EVT_MENU(PopUp_Settings, WxGimmick::OnPopUpSettings)
2459 EVT_MENU_RANGE(PopUp_Sort, PopUp_Sort+99, WxGimmick::OnPopUpSort)
2460 EVT_MENU_RANGE(PopUp_User, PopUp_User+99, WxGimmick::OnPopUpUser)
2465 EVT_TREE_BEGIN_DRAG(TreeListCtrlId, WxGimmick::OnBeginDrag)
2466 EVT_TREE_BEGIN_RDRAG(TreeListCtrlId, WxGimmick::OnBeginRDrag)
2467 EVT_TREE_END_DRAG(TreeListCtrlId, WxGimmick::OnEndDrag)
2470 EVT_TREE_BEGIN_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnBeginLabelEdit)
2471 EVT_TREE_END_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnEndLabelEdit)
2474 EVT_TREE_DELETE_ITEM(TreeListCtrlId, WxGimmick::OnDeleteItem)
2475 #if 0 // there are so many of those that logging them causes flicker
2476 EVT_TREE_GET_INFO(TreeListCtrlId, WxGimmick::OnGetInfo)
2479 EVT_TREE_SET_INFO(TreeListCtrlId, WxGimmick::OnSetInfo)
2482 EVT_TREE_ITEM_EXPANDED(TreeListCtrlId, WxGimmick::OnItemExpanded)
2483 EVT_TREE_ITEM_EXPANDING(TreeListCtrlId, WxGimmick::OnItemExpanding)
2484 EVT_TREE_ITEM_COLLAPSED(TreeListCtrlId, WxGimmick::OnItemCollapsed)
2485 EVT_TREE_ITEM_COLLAPSING(TreeListCtrlId, WxGimmick::OnItemCollapsing)
2488 EVT_TREE_SEL_CHANGED(TreeListCtrlId, WxGimmick::OnSelChanged)
2489 EVT_TREE_SEL_CHANGING(TreeListCtrlId, WxGimmick::OnSelChanging)
2491 EVT_TREE_KEY_DOWN(TreeListCtrlId, WxGimmick::OnTreeKeyDown)
2492 // ACTIVATION = DOUBLE CLICK OR ENTER ON SELECTED
2493 EVT_TREE_ITEM_ACTIVATED(TreeListCtrlId, WxGimmick::OnItemActivated)
2495 // so many differents ways to handle right mouse button clicks...
2496 // EVT_CONTEXT_MENU(WxGimmick::OnContextMenu)
2497 // EVT_TREE_ITEM_MENU is the preferred event for creating context menus
2498 // on a tree control, because it includes the point of the click or item,
2499 // meaning that no additional placement calculations are required.
2500 // EVT_TREE_ITEM_MENU(TreeListCtrlId, WxGimmick::OnItemMenu)
2502 EVT_TREE_ITEM_RIGHT_CLICK(TreeListCtrlId, WxGimmick::OnItemRightClick)
2505 // EVT_RIGHT_DOWN(WxGimmick::OnRMouseDown)
2506 // EVT_RIGHT_UP(WxGimmick::OnRMouseUp)
2507 // EVT_RIGHT_DCLICK(WxGimmick::OnRMouseDClick)
2510 //IMPLEMENT_DYNAMIC_CLASS(WxGimmick, wxTreeListCtrl)
2513 wxTree::wxTree(wxWindow *parent, const wxWindowID id,
2514 const wxPoint& pos, const wxSize& size,
2516 : wxTreeListCtrl(parent, id, pos, size, style)
2518 m_reverseSort = false;
2522 // Add some items to the tree
2523 AddTestItemsToTree(5, 2);
2529 #if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
2530 void WxGimmick::CreateButtonsImageList(int size)
2535 mTreeListCtrl->SetButtonsImageList(NULL);
2539 // Make an image list containing small icons
2540 wxImageList *images = new wxImageList(size, size, true);
2542 // should correspond to TreeListCtrlIcon_xxx enum
2545 icons[0] = wxIcon(icon3_xpm); // closed
2546 icons[1] = wxIcon(icon3_xpm); // closed, selected
2547 icons[2] = wxIcon(icon5_xpm); // open
2548 icons[3] = wxIcon(icon5_xpm); // open, selected
2550 for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
2552 int sizeOrig = icons[i].GetWidth();
2553 if ( size == sizeOrig )
2555 images->Add(icons[i]);
2559 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
2563 mTreeListCtrl->AssignButtonsImageList(images);
2566 void WxGimmick::CreateButtonsImageList(int WXUNUSED(size))
2572 int WxGimmick::OnCompareItems(const wxTreeItemId& item1,
2573 const wxTreeItemId& item2)
2575 if ( m_reverseSort )
2577 // just exchange 1st and 2nd items
2578 return mTreeListCtrl->OnCompareItems(item2, item1);
2582 return mTreeListCtrl->OnCompareItems(item1, item2);
2587 void WxGimmick::DoToggleIcon(const wxTreeItemId& item)
2590 int image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_Folder)
2593 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Normal);
2595 image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_FolderSelected)
2596 ? TreeIcon_FileSelected
2597 : TreeIcon_FolderSelected;
2598 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Selected);
2601 void WxGimmick::LogEvent(const wxChar *name, const wxTreeEvent& event)
2603 wxTreeItemId item = event.GetItem();
2606 text << _T('"') << mTreeListCtrl->GetItemText(item).c_str() << _T('"');
2608 text = _T("invalid item");
2609 // wxLogMessage(wxT("%s(%s)"), name, text.c_str());
2614 #define TREE_EVENT_HANDLER(name) \
2615 void WxGimmick::name(wxTreeEvent& event) \
2617 /* LogEvent(_T(#name), event); */ \
2618 /* SetLastItem(mTreeListCtrl->wxTreeItemId()) *;*/ \
2622 TREE_EVENT_HANDLER(OnBeginRDrag)
2623 TREE_EVENT_HANDLER(OnDeleteItem)
2624 TREE_EVENT_HANDLER(OnGetInfo)
2625 TREE_EVENT_HANDLER(OnSetInfo)
2626 //TREE_EVENT_HANDLER(OnItemExpanded)
2627 TREE_EVENT_HANDLER(OnItemExpanding)
2628 //TREE_EVENT_HANDLER(OnItemCollapsed)
2629 //TREE_EVENT_HANDLER(OnSelChanged)
2630 // TREE_EVENT_HANDLER(OnSelChanging)
2633 void WxGimmick::OnItemCollapsed(wxTreeEvent& event)
2635 // std::cout << "* Collapsed *"<<std::endl;
2638 #undef TREE_EVENT_HANDLER
2640 void WxGimmick::OnTreeKeyDown(wxTreeEvent& event)
2643 // LogKeyEvent(wxT("Tree key down "), event.GetKeyEvent());
2644 std::cout << "* Key down *"<<std::endl;
2645 if (event.GetKeyCode()==WXK_RIGHT)
2647 std::cout << "Right"<<std::endl;
2648 wxTreeItemId itemId = mTreeListCtrl->GetSelection();
2651 std::cout << "item is ok"<<std::endl;
2652 wxPoint clientpt = event.GetPoint();
2653 wxPoint screenpt = ClientToScreen(clientpt);
2654 ShowMenu(itemId, clientpt);
2659 std::cout << "NOT Right"<<std::endl;
2664 void WxGimmick::OnBeginDrag(wxTreeEvent& event)
2666 wxTreeItemId id = event.GetItem();
2667 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2668 // std::cout << "OnBeginDrag("<<id<<")"<<std::endl;
2669 if (data->IsDatabase())
2671 // std::cout << "-- IS ROOT"<<std::endl;
2674 else if (data->IsDicomNode())
2676 // std::cout << "-- IS NODE"<<std::endl;
2679 // need to explicitly allow drag
2680 if ( event.GetItem() != GetDatabaseItem() )
2682 m_draggedItem = event.GetItem();
2684 wxPoint clientpt = event.GetPoint();
2685 wxPoint screenpt = ClientToScreen(clientpt);
2687 wxLogMessage(wxT("OnBeginDrag: started dragging %s at screen coords (%i,%i)"),
2688 GetItemText(m_draggedItem).c_str(),
2689 screenpt.x, screenpt.y);
2695 wxLogMessage(wxT("OnBeginDrag: this item can't be dragged."));
2700 void WxGimmick::OnEndDrag(wxTreeEvent& event)
2702 wxTreeItemId id = event.GetItem();
2703 // std::cout << "OnEndDrag("<<id<<")"<<std::endl;
2704 if (!id.IsOk()) return;
2705 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2706 if (data->IsDatabase())
2708 // std::cout << "-- IS ROOT"<<std::endl;
2710 else if (data->IsDicomNode())
2712 // std::cout << "-- IS NODE"<<std::endl;
2716 wxTreeItemId itemSrc = m_draggedItem,
2717 itemDst = event.GetItem();
2718 m_draggedItem = (wxTreeItemId)0l;
2720 // where to copy the item?
2721 if ( itemDst.IsOk() && !ItemHasChildren(itemDst) )
2723 // copy to the parent then
2724 itemDst = GetItemParent(itemDst);
2727 if ( !itemDst.IsOk() )
2729 wxLogMessage(wxT("OnEndDrag: can't drop here."));
2734 wxString text = GetItemText(itemSrc);
2735 wxLogMessage(wxT("OnEndDrag: '%s' copied to '%s'."),
2736 text.c_str(), GetItemText(itemDst).c_str());
2738 // just do append here - we could also insert it just before/after the item
2739 // on which it was dropped, but this requires slightly more work... we also
2740 // completely ignore the client data and icon of the old item but could
2741 // copy them as well.
2743 // Finally, we only copy one item here but we might copy the entire tree if
2744 // we were dragging a folder.
2745 int image = wxGetApp().ShowImages() ? TreeIcon_File : -1;
2746 AppendItem(itemDst, text, image);
2751 //====================================================================
2752 void WxGimmick::OnBeginLabelEdit(wxTreeEvent& event)
2754 // std::cout << "OnBeginLabelEdit"<<std::endl;
2755 wxTreeItemId id = event.GetItem();
2756 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2757 // If not a root : veto
2758 if (data->IsDatabase())
2765 //====================================================================
2767 //====================================================================
2768 void WxGimmick::OnEndLabelEdit(wxTreeEvent& event)
2770 // std::cout << "OnEndLabelEdit"<<std::endl;
2771 wxTreeItemId id = event.GetItem();
2772 TreeItemData *data = GetItemData(id);
2773 // If not a database : bug !
2774 if (data->IsDatabase())
2776 data->GetDicomNode()->GetDicomDatabase()->SetName(wx2std(event.GetLabel()));
2777 mFieldsView->UpdateValues(data->GetDicomNode());
2781 std::cerr<< "!!!! Internal error : send bug report !!!!"<<std::endl;
2784 //====================================================================
2787 void WxGimmick::OnItemCollapsing(wxTreeEvent& event)
2789 // wxLogMessage(wxT("OnItemCollapsing"));
2791 // for testing, prevent the user from collapsing the first child folder
2792 wxTreeItemId itemId = event.GetItem();
2795 if ( IsTestItem(itemId) )
2797 wxMessageBox(wxT("You can't collapse this item."));
2805 //====================================================================
2806 void WxGimmick::ShowHelp()
2811 mHelpWindow = new WxGimmickHelpWindow(this);
2813 mHelpWindow->CenterOnParent();
2814 mHelpWindow->ShowModal();
2817 //====================================================================
2823 //================================================================
2824 //================================================================
2825 //================================================================
2826 //================================================================
2827 //================================================================
2829 //================================================================
2830 //================================================================
2831 //================================================================
2832 //================================================================
2833 //================================================================
2839 // ----------------------------------------------------------------------------
2841 // ----------------------------------------------------------------------------
2843 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_DRAG)
2844 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_RDRAG)
2845 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_DELETE_ITEM)
2846 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_GET_INFO)
2847 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SET_INFO)
2848 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDED)
2849 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDING)
2850 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSED)
2851 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSING)
2854 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT)
2855 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_LABEL_EDIT)
2858 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED)
2859 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGING)
2860 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_KEY_DOWN)
2861 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU)
2862 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_ITEM_STYLE_CHANGED)
2864 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_ACTIVATED)
2865 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK)
2866 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK)
2867 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_DRAG)
2868 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK)
2869 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP)
2870 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MENU)
2872 // ----------------------------------------------------------------------------
2874 // ----------------------------------------------------------------------------
2876 IMPLEMENT_ABSTRACT_CLASS(WxGimmickEvent, wxNotifyEvent)
2879 WxGimmickEvent::WxGimmickEvent(wxEventType commandType,
2881 const wxTreeItemId& item)
2883 wxNotifyEvent(commandType, tree->GetId()),
2887 // m_editCancelled = false;
2889 SetEventObject(tree);
2892 SetClientObject(tree->mTreeListCtrl->GetItemData(item));
2895 WxGimmickEvent::WxGimmickEvent(wxEventType commandType, int id)
2897 wxNotifyEvent(commandType, id),
2901 // m_editCancelled = false;
2904 WxGimmickEvent::WxGimmickEvent(const WxGimmickEvent & event)
2906 wxNotifyEvent(event),
2910 m_evtKey = event.m_evtKey;
2911 m_item = event.m_item;
2912 m_itemOld = event.m_itemOld;
2913 mColor = event.mColor;
2914 mUserData = event.mUserData;
2915 // m_pointDrag = event.m_pointDrag;
2916 // m_label = event.m_label;
2917 // m_editCancelled = event.m_editCancelled;
2927 //================================================================
2928 //================================================================
2929 //================================================================
2930 //================================================================
2931 //================================================================
2932 WxGimmickFrame::WxGimmickFrame( wxWindow *parent,
2935 : wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size)
2937 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
2938 mWxGimmick = new WxGimmick(this,-1,
2941 sizer->Add(mWxGimmick,1,wxGROW);
2943 SetAutoLayout(true);
2946 //================================================================
2948 //================================================================
2949 WxGimmickFrame::~WxGimmickFrame()
2952 //================================================================
2954 //================================================================
2955 void WxGimmickFrame::OnSelChanged(WxGimmickEvent& event)
2957 // std::cout << "+++++ WxGimmickFrame::OnSelChanged ++++++++++"
2959 std::vector<std::string> file;
2960 // mWxGimmick->GetSelectedImages(file);
2962 std::vector<std::string>::iterator i;
2963 for (i=file.begin();i!=file.end();++i)
2965 std::cout << "'" << *i << "'" << std::endl;
2967 std::cout << "++++++++++++++++++++" << std::endl;
2970 //================================================================
2972 //================================================================
2973 BEGIN_EVENT_TABLE(WxGimmickFrame, wxFrame)
2974 EVT_TREEVIEWLIST_SEL_CHANGED(-1,WxGimmickFrame::OnSelChanged)
2976 //================================================================