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>
26 #include <boost/filesystem.hpp>
27 #include <boost/algorithm/string.hpp>
31 //================================================================
32 const int WxGimmick::UserMenuFirstId = 1000;
33 //================================================================
35 //================================================================
48 //================================================================
50 //================================================================
53 PopUp_NewCollection = 100,
54 PopUp_OpenCollection = 101,
55 PopUp_CloseCollection = 102,
56 PopUp_DeleteCollection = 103,
57 PopUp_AddDirectory = 110,
59 PopUp_AddRawFile = 112,
64 PopUp_User = WxGimmick::UserMenuFirstId,
66 //================================================================
68 //================================================================
69 #define TreeListCtrlId 10000
70 //================================================================
72 //================================================================
73 const icon_id Icon[5] = { Icon_Database,
78 //================================================================
81 //================================================================
82 class WxGimmickDicomNodeData : public DicomNodeData
85 WxGimmickDicomNodeData
86 (WxGimmickTreeItemData* d = 0) :
90 ~WxGimmickDicomNodeData();
92 WxGimmickTreeItemData* GetTreeItemData()
93 { return mTreeItemData; }
94 void SetTreeItemData( WxGimmickTreeItemData* d)
95 { mTreeItemData = d; }
96 inline bool IsLoaded() { return mLoaded; }
97 inline void SetLoaded(bool v) { mLoaded = v; }
100 WxGimmickTreeItemData* mTreeItemData;
103 //================================================================
106 //================================================================
107 class WxGimmickTreeItemData : public wxTreeItemData
110 WxGimmickTreeItemData(DicomNode* node)
120 WxGimmickDicomNodeData* data =
121 node->GetData<WxGimmickDicomNodeData*>();
124 if (data->GetTreeItemData()!=0)
126 std::cout << "WxGimmickTreeItemData ERROR ****"
130 data->SetTreeItemData(this);
133 node->SetData( new WxGimmickDicomNodeData(this) );
134 if (node->GetType()==DicomNode::Database)
144 ~WxGimmickTreeItemData()
148 WxGimmickDicomNodeData* data =
149 mDicomNode->GetData<WxGimmickDicomNodeData*>();
150 if (data) data->SetTreeItemData(0);
154 inline void ResetDicomNode()
159 inline void SetItemId ( const wxTreeItemId& item ) { mItemId = item; }
160 inline const wxTreeItemId& GetItemId() const { return mItemId; }
162 inline bool IsDefault() const { return (mType == 0); }
163 inline bool IsDatabase() const { return (mType == 2); }
164 inline bool IsDicomNode() const { return (mType == 1); }
166 inline DicomNode* GetDicomNode() { return mDicomNode; }
167 inline long& UpdateTime() { return mUpdateTime; }
168 inline bool IsLoaded()
170 mDicomNode->GetData<WxGimmickDicomNodeData*>()->IsLoaded();
172 inline void SetLoaded(bool v)
174 mDicomNode->GetData<WxGimmickDicomNodeData*>()->SetLoaded(v);
177 inline int GetUserFlags() const { return mUserFlags; }
178 inline void SetUserFlags(int f) { mUserFlags = f; }
181 // The type of item :
184 // 2 = DicomNode of type Database
186 wxTreeItemId mItemId;
187 DicomNode* mDicomNode;
192 //================================================================
195 //================================================================
196 WxGimmickDicomNodeData::~WxGimmickDicomNodeData()
200 mTreeItemData->ResetDicomNode();
203 //================================================================
212 //================================================================
213 class WxGimmickSettingsDialog : public wxDialog
216 WxGimmickSettingsDialog(wxWindow *parent);
217 ~WxGimmickSettingsDialog();
221 //================================================================
250 //================================================================
251 //================================================================
252 //================================================================
253 //================================================================
254 //================================================================
255 //================================================================
256 //================================================================
257 WxGimmick::WxGimmick(wxWindow *parent,
263 : wxPanel(parent,id,pos,size),
264 mSelectionType(image_type),
265 mSaveConfigurationOnClose(true),
268 // Initialize image size corresponding to current selection
269 switch (mSelectionType)
271 case GIMMICK_2D_IMAGE_SELECTION : mSelectionMaxImageDimension = 2; break;
272 case GIMMICK_3D_IMAGE_SELECTION : mSelectionMaxImageDimension = 3; break;
273 case GIMMICK_4D_IMAGE_SELECTION : mSelectionMaxImageDimension = 4; break;
274 default : mSelectionMaxImageDimension = 0;
278 // Start the threads ...
282 SetDatabaseExtension("sqlite3");
283 // Create the UserSettings dir if does not exist
284 CreateUserSettingsDirectory();
285 // Sets the current directory to the Setting dir
286 mCurrentDirectory = std2wx(GetUserSettingsDirectory());
288 // Window layout creation
289 wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
292 mSplitter1 = new wxSplitterWindow( this, -1);
294 // TreeCtrl on the left
299 //| wxTR_LINES_AT_ROOT
300 | wxTR_FULL_ROW_HIGHLIGHT
307 | wxTR_EDIT_LABELS //Use this style if you wish the user to be able to edit labels in the tree list control.
308 //wxTR_NO_BUTTONS For convenience to document that no buttons are to be drawn.
309 | wxTR_HAS_BUTTONS //Use this style to show + and - buttons to the left of parent items.
310 | 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.
311 //wxTR_NO_LINES Use this style to hide vertical level connectors.
312 | 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.)
313 | 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.
314 | 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.
315 // wxTR_ROW_LINES // Use this style to draw a contrasting border between displayed rows.
316 // 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.
317 // 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.
318 | 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.
319 | wxTR_EXTENDED // Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases.)
320 //wxTR_DEFAULT_STYLE The set of flags that are closest to the defaults for the native control for a particular toolkit.
321 //| wxTR_VIRTUAL //The application provides items text on demand.
324 mTreeListCtrl = new wxTreeListCtrl(mSplitter1,
330 mTreeListCtrl->SetIndent(0);
331 mTreeListCtrl->SetLineSpacing(5);
336 wxPanel *rpanel = new wxPanel( mSplitter1, -1 );
338 wxBoxSizer *rsizer = new wxBoxSizer(wxHORIZONTAL);
339 // Right panel top/bottom split
340 mSplitter2 = new wxSplitterWindow( rpanel , -1);
343 mPanelImage = new wxPanel(mSplitter2,-1);
344 mPanelImage->SetBackgroundColour( wxColour(0,0,0) );
346 wxBoxSizer *isizer = new wxBoxSizer(wxHORIZONTAL );
347 mPanelImage->SetSizer( isizer );
349 // Fields view (bottom)
350 mFieldsView = new WxGimmickFieldsView(mSplitter2,-1,
354 mFieldsView->SetColors
355 ( GetSettings().Colour(DicomNode::Database),
356 GetSettings().BgColour(DicomNode::Database),
357 GetSettings().Colour(DicomNode::Patient),
358 GetSettings().BgColour(DicomNode::Patient),
359 GetSettings().Colour(DicomNode::Study),
360 GetSettings().BgColour(DicomNode::Study),
361 GetSettings().Colour(DicomNode::Series),
362 GetSettings().BgColour(DicomNode::Series),
363 GetSettings().Colour(DicomNode::Image),
364 GetSettings().BgColour(DicomNode::Image));
368 int wsize = size.GetWidth();
369 int hsize = size.GetHeight();
370 int previewhsize = 150;
371 int previewwsize = 400;
373 mSplitter2->SetMinimumPaneSize( previewhsize );
374 mSplitter2->SplitHorizontally( mPanelImage, mFieldsView,
375 hsize - previewhsize);
377 rsizer->Add( mSplitter2,1,wxGROW ,0);
379 rpanel->SetAutoLayout(true);
380 rpanel->SetSizer( rsizer );
384 mInteractor = new wxVTKRenderWindowInteractor(mPanelImage,-1);
385 mInteractor->UseCaptureMouseOn();
387 mViewer = vtkImageViewer2::New();
388 mViewer->SetupInteractor ( mInteractor );
389 mViewer->SetInput(mReader.GetImage(""));
391 isizer-> Add( mInteractor ,1,wxGROW ,0);
393 topsizer->Add( mSplitter1,1,wxGROW ,0);
396 mSplitter1->SetMinimumPaneSize( 200 );
397 mSplitter1->SplitVertically(mTreeListCtrl,
399 wsize - previewwsize );
402 // ProcessImageEvents();
403 SetSizer( topsizer );
406 mDatabaseListFile = GetUserSettingsDirectory();
407 mDatabaseListFile += "collections.txt";
412 ShowImage(mReader.GetImage(""));
415 //================================================================
419 #define VALID_FILE_SEPARATOR "\\"
420 #define INVALID_FILE_SEPARATOR "/"
422 #define INVALID_FILE_SEPARATOR "\\"
423 #define VALID_FILE_SEPARATOR "/"
426 //================================================================
427 const std::string& WxGimmick::GetUserSettingsDirectory()
429 if (mUserSettingsDirectory.size()==0)
431 #if defined(__GNUC__)
432 mUserSettingsDirectory = getenv("HOME");
433 #elif defined(_WIN32)
434 mUserSettingsDirectory = getenv("USERPROFILE");
436 mUserSettingsDirectory += "/.gimmick/";
437 boost::algorithm::replace_all( mUserSettingsDirectory,
438 INVALID_FILE_SEPARATOR ,
439 VALID_FILE_SEPARATOR);
441 return mUserSettingsDirectory;
443 //================================================================
445 //========================================================================
446 void WxGimmick::CreateUserSettingsDirectory()
448 if (! boost::filesystem::is_directory( GetUserSettingsDirectory() ) )
450 creaMessage("Gimmick!",1,"==> Directory '"<<GetUserSettingsDirectory()<<"' "
451 << "does not exist : creating it"<<std::endl);
453 if ( ! boost::filesystem::create_directory( GetUserSettingsDirectory() ) )
455 creaMessage("Gimmick!",1,"!! ERROR CREATING '"<<GetUserSettingsDirectory()<<"'");
459 //========================================================================
461 //================================================================
462 WxGimmick::~WxGimmick()
464 // std::cout << "WxGimmick::~WxGimmick()" <<std::endl;
465 if (mSaveConfigurationOnClose) SaveConfiguration();
468 // std::cout << "Reader stopped"<<std::endl;
470 DicomDatabaseListType::iterator i;
471 for (i =GetDicomDatabaseList().begin();
472 i!=GetDicomDatabaseList().end();
480 //================================================================
483 //================================================================
484 void WxGimmick::RebuildView()
488 mTreeListCtrl->DeleteRoot(); //DeleteAllItems();
489 // mTreeDefaultItemId = wxTreeItemId();
492 int nbattr = mSettings.GetMaxNumberOfColumns();
494 for (int j=0;j<nbattr; j++)
496 mTreeListCtrl->AddColumn (_T(""),
497 200, //DEFAULT_COL_WIDTH,
503 mTreeListCtrl->SetMainColumn (0);
504 mTreeListCtrl->SetColumnEditable (0, true);
506 mTreeRootId = mTreeListCtrl->AddRoot( _T(""),Icon_Root,Icon_Root);
508 // The collections columns legends
509 mCollectionsTitlesItemId =
510 CreateChildrenColumnsTitles(mTreeRootId,DicomNode::Database);
512 DicomDatabaseListType::iterator i;
513 for (i =GetDicomDatabaseList().begin();
514 i!=GetDicomDatabaseList().end();
517 UpdateDicomDatabaseView(*i);
520 mTreeListCtrl->Expand(mTreeRootId);
522 // mTreeListCtrl->ExpandAll(mTreeRootId);
523 // std::cout << "EO RebuildAll"<<std::endl;
525 //================================================================
529 //================================================================
530 void WxGimmick::UpdateDicomDatabaseView(DicomDatabase* db)
536 // Does the db exist ?
537 wxTreeItemIdValue cookie;
538 for (dbid = mTreeListCtrl->GetFirstChild(mTreeRootId,cookie);
540 dbid = mTreeListCtrl->GetNextChild(mTreeRootId,cookie))
542 data = (TreeItemData *)mTreeListCtrl->GetItemData(dbid);
543 if ((data->IsDatabase())&&(data->GetDicomNode()==db)) break;
546 // Not found : create
550 int iconid = Icon[DicomNode::Database];
553 // std::cout << " -> Creating item for '"<<db->GetLabel()<<"'"<<std::endl;
554 data = new TreeItemData(db);
555 dbid = mTreeListCtrl->AppendItem( mTreeRootId,
556 std2wx(db->GetLabel()),
560 data->SetItemId(dbid);
561 mTreeListCtrl->SetItemTextColour
562 (dbid,mSettings.Colour(DicomNode::Database));
563 mTreeListCtrl->SetItemBackgroundColour
564 (dbid,mSettings.BgColour(DicomNode::Database));
566 // The patients columns legends
567 CreateChildrenColumnsTitles(dbid,DicomNode::Patient);
570 // Increase UpdateTime to detect obsolete items after
572 data->UpdateTime()++;
574 DicomNode::ChildrenListType::iterator j;
575 for (j= db->GetChildrenList().begin();
576 j!=db->GetChildrenList().end();
579 UpdateDicomNodeView(*j,dbid);
582 DeleteObsoleteChildren(dbid);
584 mTreeListCtrl->EnsureVisible(dbid);
587 //================================================================
589 //================================================================
590 void WxGimmick::UpdateDicomNodeView(DicomNode* n,
591 const wxTreeItemId& parent)
595 // std::cout << "* UpdateDicomNodeView("<<n->GetLabel()<<")"<<std::endl;
597 wxTreeItemId newparent = parent;
600 if ((!mSettings.MergeStudySeries()) ||
601 (n->GetType() != DicomNode::Study))
603 // Does the item exist ?
604 wxTreeItemIdValue cookie;
605 for (newparent = mTreeListCtrl->GetFirstChild(parent,cookie);
607 newparent = mTreeListCtrl->GetNextChild(parent,cookie))
609 data = (TreeItemData *)mTreeListCtrl->GetItemData(newparent);
610 if (data->GetDicomNode() == n) break;
612 // Not found : create
613 if (!newparent.IsOk())
615 int image(Icon[n->GetType()]);
616 wxColour *colour(&mSettings.Colour(n->GetType()));
617 wxColour *bgcolour(&mSettings.BgColour(n->GetType()));
619 if (n->GetType()==DicomNode::Image)
621 // std::cout << "!!!Image"<<std::endl;
622 if (n->GetData<NodeData*>()!=0)
624 // std::cout << ">> n->GetData<NodeData*>()!=0" << std::endl;
625 if (n->GetData<NodeData*>()->IsLoaded())
627 colour = &mSettings.LoadedImageColour();
629 // std::cout << "<< n->GetData<NodeData*>()!=0" << std::endl;
633 data = new TreeItemData(n);
634 newparent = mTreeListCtrl->AppendItem(parent,
638 data->SetItemId(newparent);
639 mTreeListCtrl->SetItemTextColour(newparent,*colour);
640 mTreeListCtrl->SetItemBackgroundColour(newparent,*bgcolour);
642 UpdateColumns(newparent);
645 if (n->GetType()!=DicomNode::Image)
647 CreateChildrenColumnsTitles(newparent,n->GetType()+1);
653 UpdateColumns(newparent,true);
656 // synchonise update time with parent
657 TreeItemData * parent_data =
658 (TreeItemData *)mTreeListCtrl->GetItemData(parent);
659 data->UpdateTime() = parent_data->UpdateTime();
662 DicomNode::ChildrenListType::iterator i;
663 for (i=n->GetChildrenList().begin();
664 i!=n->GetChildrenList().end();
667 UpdateDicomNodeView(*i,newparent);
670 if (n->GetType() != DicomNode::Image)
671 DeleteObsoleteChildren(newparent);
674 //================================================================
676 //================================================================
677 void WxGimmick::UpdateColumns(wxTreeItemId& item,
681 (TreeItemData *)mTreeListCtrl->GetItemData(item);
682 DicomNode* node = data->GetDicomNode();
686 // Update only the first field (for #children update)
687 DicomNode* node2 = node;
688 // If Study and Series level are merged and node type is Series
689 // then have to get back to the Study level
690 if ((mSettings.MergeStudySeries())&&
691 (node->GetType() == DicomNode::Series))
692 node2 = node->GetParent();
695 lab += node2->GetFieldValueMap()
696 [ mSettings.GetColumnList(node2->GetType())[0].Key ];
698 if (node->GetType() != DicomNode::Image)
700 if (node->GetChildrenList().size()>0)
703 sprintf(sz," [%d]",node->GetNumberOfChildren());
707 mTreeListCtrl->SetItemText(item,std2wx(lab));
713 Settings::ColumnListType::iterator col;
714 // If Study and Series level are merged and node type is Series
715 // then have to fill the Study level cols first
716 if ((mSettings.MergeStudySeries())&&
717 (node->GetType() == DicomNode::Series))
719 DicomNode* node2 = node->GetParent();
720 for (col = mSettings.GetColumnList(node2->GetType()).begin();
721 col != mSettings.GetColumnList(node2->GetType()).end();
724 std::string s = node2->GetFieldValueMap()[col->Key];
729 sprintf(sz," [%d]",node->GetNumberOfChildren());
732 mTreeListCtrl->SetItemText (item, c, std2wx(s));
737 for (col = mSettings.GetColumnList(node->GetType()).begin();
738 col != mSettings.GetColumnList(node->GetType()).end();
741 std::string s = node->GetFieldValueMap()[col->Key];
742 if ((c==0)&&(node->GetType() != DicomNode::Image))
745 sprintf(sz," [%d]",node->GetNumberOfChildren());
748 mTreeListCtrl->SetItemText (item, c, std2wx(s));
754 //================================================================
756 //================================================================
757 wxTreeItemId WxGimmick::CreateChildrenColumnsTitles
761 // Creates the sub-level columns titles
763 = new TreeItemData(0);
764 wxTreeItemId id = mTreeListCtrl->AppendItem( item,
770 mTreeListCtrl->SetItemFont(id, *wxITALIC_FONT);
771 mTreeListCtrl->SetItemTextColour(id, mSettings.Colour(t));
772 mTreeListCtrl->SetItemBackgroundColour(id, mSettings.BgColour(t));
773 UpdateColumnsTitles(id,t);
776 //================================================================
778 //================================================================
779 void WxGimmick::UpdateColumnsTitles(wxTreeItemId& item,
782 // std::cout << "Update columns titles "<<t<<std::endl;
784 Settings::ColumnListType::iterator col;
785 for (col = mSettings.GetColumnList(t).begin();
786 col != mSettings.GetColumnList(t).end();
789 // std::cout << col->Name << std::endl;
790 mTreeListCtrl->SetItemText (item, c, std2wx(col->Name));
794 //================================================================
797 //================================================================
798 void WxGimmick::DeleteObsoleteChildren(wxTreeItemId& id)
801 TreeItemData * parent_data =
802 (TreeItemData *)mTreeListCtrl->GetItemData(id);
805 wxTreeItemIdValue cookie;
806 std::vector<wxTreeItemId> children;
807 for (child = mTreeListCtrl->GetFirstChild(id,cookie);
809 child = mTreeListCtrl->GetNextChild(id,cookie))
811 children.push_back(child);
813 std::vector<wxTreeItemId>::iterator i;
814 for (i=children.begin();i!=children.end();++i)
817 (TreeItemData *)mTreeListCtrl->GetItemData(*i);
819 ((data->GetDicomNode()>0) &&
820 ((data->UpdateTime() != parent_data->UpdateTime()))) ||
821 ((data->IsDicomNode()) &&
822 (data->GetDicomNode()==0))
825 // std::cout << "DOBSC="<<mTreeListCtrl->GetItemText(*i)<<std::endl;
826 mTreeListCtrl->Delete(*i);
830 //================================================================
832 //================================================================
833 void WxGimmick::OpenOrNewDatabase(bool open)
837 long style = wxFD_SAVE | wxFD_OVERWRITE_PROMPT;
838 if (open) style = wxOPEN | wxFILE_MUST_EXIST;
839 std::string wc("*.");
840 wc += GetDatabaseExtension();
842 // TO DO : Handler give their wildcards
843 wxFileDialog* FD = new wxFileDialog( 0,
851 if (FD->ShowModal()!=wxID_OK) return;
853 std::string filename = wx2std (FD->GetPath());
854 mCurrentDirectory = FD->GetDirectory();
858 boost::filesystem::path filepath(filename);
859 boost::filesystem::change_extension(filepath,GetDatabaseExtension());
860 if ( boost::filesystem::exists(filepath) )
862 boost::filesystem::remove(filepath);
864 LG : works on Linux but not Windows :
865 if ( ! boost::filesystem::remove(filepath) )
867 wxMessageBox(_T("Could not overwrite ")
868 +std2wx(filepath.string()),
879 DicomDatabase* db = new DicomDatabase(filename);
886 wxMessageBox(_T("An error occured while opening ")
896 wxGetTextFromUser(_T("Enter collection name"),_T("New collection"),
898 db->SetName(wx2std(collname));
903 wxMessageBox(_T("An error occured while creating ")
911 GetDicomDatabaseList().push_back(db);
912 UpdateDicomDatabaseView(db);
915 //================================================================
918 //================================================================
919 void WxGimmick::LoadConfiguration()
922 // std::cout << "WxGimmick : Reading config"<<std::endl;
924 // std::cout << "==> Loading collections from '"<<mDatabaseListFile
928 s.open(mDatabaseListFile.c_str());
935 if (str.size()==0) continue;
937 std::vector<std::string> tokens;
938 boost::split( tokens, str, boost::is_any_of("\t") );
940 DicomDatabase* db = new DicomDatabase(tokens[0]);
942 // std::cout << " -> Loading collection '"<<tokens[0]<<"'"<<std::endl;
944 if (tokens.size()==2)
946 db->SetName(tokens[1]);
951 GetDicomDatabaseList().push_back(db);
952 db->DBLoadChildren(db,DicomNode::Patient);
953 if (mSettings.HasActiveComparator(DicomNode::Patient))
956 ( mSettings.GetActiveComparator(DicomNode::Patient) );
961 // std::cout << " ... ERROR !"<<std::endl;
969 std::cout << "ERROR opening "<<mDatabaseListFile<<std::endl;
973 mTreeListCtrl->SetBackgroundColour(mSettings.BgColour(DicomNode::Database));
974 if (GetDicomDatabaseList().begin() !=
975 GetDicomDatabaseList().end() )
977 mFieldsView->UpdateFields(*GetDicomDatabaseList().begin());
983 //================================================================
985 //================================================================
986 void WxGimmick::SaveConfiguration()
989 creaMessage("Gimmick!",1,"Gimmick! : Saving configuration..."<<std::endl);
991 creaMessage("Gimmick!",1,"Gimmick! : ==> Saving collections in '"
992 <<mDatabaseListFile<<"'"<<std::endl);
995 s.open(mDatabaseListFile.c_str());
998 creaError("Gimmick! : error opening '"<<mDatabaseListFile<<"'");
1001 DicomDatabaseListType::iterator i;
1002 for (i =GetDicomDatabaseList().begin();
1003 i!=GetDicomDatabaseList().end();
1006 s << (*i)->GetFileName() << "\t";
1007 s << (*i)->GetName() << std::endl;
1013 //================================================================
1016 //================================================================
1017 void WxGimmick::OnClose(wxCloseEvent& event)
1019 if (mSaveConfigurationOnClose) SaveConfiguration();
1021 //================================================================
1023 //================================================================
1024 void WxGimmick::OnItemActivated(wxTreeEvent& event)
1030 // std::cout << "OnItemActivated" <<std::endl;
1031 wxTreeItemId itemId = event.GetItem();
1032 if (mTreeListCtrl->IsExpanded(itemId))
1034 mTreeListCtrl->Collapse(itemId);
1038 mTreeListCtrl->Expand(itemId);
1041 //================================================================
1043 //================================================================
1044 void WxGimmick::LoadChildren(wxTreeItemId& id)
1046 TreeItemData *item = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1049 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1050 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1053 // If children not already loaded : do it
1055 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1056 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1059 // Some new children loaded
1061 if (mSettings.HasActiveComparator
1062 (item->GetDicomNode()->GetType()+1))
1064 /* std::cout << "Sorting using '"
1065 << mSettings.GetActiveComparator
1066 (item->GetDicomNode()->GetType()+1).GetName()
1069 item->GetDicomNode()->SortChildren
1070 ( mSettings.GetActiveComparator
1071 (item->GetDicomNode()->GetType()+1)
1073 // std::cout << "ok"<<std::endl;
1076 DicomNode::ChildrenListType::iterator i;
1077 for (i=item->GetDicomNode()->GetChildrenList().begin();
1078 i!=item->GetDicomNode()->GetChildrenList().end();
1081 UpdateDicomNodeView(*i,id);
1084 // EO If children not already loaded
1088 //================================================================
1091 //================================================================
1092 void WxGimmick::OnItemExpanded(wxTreeEvent& event)
1095 // std::cout << "* Expanded *"<<std::endl;
1100 wxTreeItemId itemId = event.GetItem();
1101 LoadChildren(itemId);
1105 // expand if collapsed and collapse if expanded ...
1106 TreeItemData *item =
1107 (TreeItemData *)mTreeListCtrl->GetItemData(itemId);
1110 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1111 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1114 // If children not already loaded : do it
1116 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1117 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1121 // Some new children loaded
1123 if (mSettings.HasActiveComparator
1124 (item->GetDicomNode()->GetType()+1))
1126 /* std::cout << "Sorting using '"
1127 << mSettings.GetActiveComparator
1128 (item->GetDicomNode()->GetType()+1).GetName()
1131 item->GetDicomNode()->SortChildren
1132 ( mSettings.GetActiveComparator
1133 (item->GetDicomNode()->GetType()+1)
1135 // std::cout << "ok"<<std::endl;
1138 // If images : sort them
1139 if (item->IsDicomNode())
1141 if (item->GetDicomNode()->GetType()==DicomNode::Series)
1145 LexicographicalDicomNodeComparator compare;
1146 // DicomNodeImageImageNumberComparator c1;
1148 DicomNodeImageSliceLocationComparator c1;
1149 DicomNodeImageImageNumberComparator c2;
1150 DicomNodeImageFileNameComparator cn;
1154 // std::cout << "SORT"<<std::endl;
1155 item->GetDicomNode()->SortChildren(compare);
1156 // std::cout << "EO SORT"<<std::endl;
1164 DicomNode::ChildrenListType::iterator i;
1165 for (i=item->GetDicomNode()->GetChildrenList().begin();
1166 i!=item->GetDicomNode()->GetChildrenList().end();
1169 UpdateDicomNodeView(*i,itemId);
1172 // EO If children not already loaded
1175 // mTreeListCtrl->Expand(itemId);
1178 //================================================================
1182 //=====================================================================
1183 void WxGimmick::InsertRoot(wxTreeItemId& id, Root* r)
1186 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1191 data->GetDicomNode()->GetDicomDatabase()->LoadAll();
1192 printf(">>>>>> Time to load all = %ldms \n",sw.Time());
1194 UpdateRootView(data->GetDicomNode()->GetDicomDatabase());
1197 if (data->IsDicomNode())
1200 r->Insert(data->GetDicomNode());
1201 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1204 else if (data->IsDatabase())
1207 DicomNode::ChildrenListType::iterator j;
1208 for (j= data->GetDicomNode()->GetChildrenList().begin();
1209 j!=data->GetDicomNode()->GetChildrenList().end();
1214 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1220 //=====================================================================
1224 //=================================================
1225 void WxGimmick::DeleteDicomDatabase(wxTreeItemId& id,
1229 DicomDatabaseListType::iterator i = find(GetDicomDatabaseList().begin(),
1230 GetDicomDatabaseList().end(),
1233 GetDicomDatabaseList().erase(i);
1234 mTreeListCtrl->Delete(id);
1236 //=================================================
1240 //=====================================================================
1242 void WxGimmick::OnItemRightClick(wxTreeEvent& event)
1245 wxTreeItemId itemId = event.GetItem();
1248 wxPoint clientpt = event.GetPoint();
1249 wxPoint screenpt = ClientToScreen(clientpt);
1250 ShowMenu(itemId, clientpt);
1254 //=====================================================================
1258 //=====================================================================
1259 void WxGimmick::ShowMenu(wxTreeItemId id, const wxPoint& pt)
1262 // std::cout << "ShowMenu" <<std::endl;
1264 TreeItemData *data =
1265 (TreeItemData *)mTreeListCtrl->GetItemData(id);
1271 title << wxT("Menu for ") << mTreeListCtrl->GetItemText(id);
1275 title = wxT("Menu for no particular item");
1282 if (id==mCollectionsTitlesItemId)
1284 menu.Append(PopUp_NewCollection, _T("&New collection"));
1285 menu.Append(PopUp_OpenCollection, _T("&Open collection"));
1289 if (data->IsDatabase())
1291 wxMenu* addmenu = new wxMenu;
1292 addmenu->Append(PopUp_AddDirectory, _T("Scan &Directory"));
1293 addmenu->Append(PopUp_AddFile, _T("Select &File(s)"));
1294 // addmenu->Append(PopUp_AddRawFile, _T("Add &Raw image"));
1295 menu.AppendSubMenu(addmenu, _T("&Add image(s) to collection..."));
1296 menu.Append(PopUp_CloseCollection, _T("&Close collection"));
1297 menu.Append(PopUp_DeleteCollection, _T("&Delete collection"));
1299 if (data->IsDicomNode())
1303 std::string str("&Remove ");
1304 str += data->GetDicomNode()->GetTypeName();
1305 menu.Append(PopUp_Remove, std2wx(str));
1309 if ((data->GetDicomNode()>0)&&
1310 ( data->GetDicomNode()->GetType()<DicomNode::Image))
1312 int ctype = data->GetDicomNode()->GetType()+1;
1313 if (mSettings.HasActiveComparator(ctype))
1315 wxMenu* sortmenu = new wxMenu;
1317 Settings::ComparatorsList::iterator i;
1318 for (i =mSettings.GetComparatorsList(ctype).begin();
1319 i !=mSettings.GetComparatorsList(ctype).end();
1322 sortmenu->AppendRadioItem(PopUp_Sort+n, std2wx(i->GetName()));
1326 sortmenu->Check(PopUp_Sort+
1327 mSettings.GetActiveComparatorIndex(ctype)
1330 std::string sortmenustr("&Sort ");
1331 sortmenustr += DicomNode::GetPluralTypeName(ctype);
1332 sortmenustr += " by...";
1333 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1334 menu.AppendSubMenu(sortmenu,std2wx(sortmenustr));
1337 item->GetDicomNode()->SortChildren
1338 ( mSettings.GetActiveComparator
1339 (item->GetDicomNode()->GetType()+1)
1341 std::cout << "ok"<<std::endl;
1346 // Event : user can customize the menu
1348 ev(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU,this,id);
1352 ev.SetDicomNode(data->GetDicomNode());
1354 GetEventHandler()->ProcessEvent(ev);
1357 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1358 menu.Append(PopUp_Settings, wxT("&Settings..."));
1359 menu.Append(PopUp_About, wxT("&About..."));
1364 wxMenu* newmenu = new wxMenu;
1365 wxMenu* openmenu = new wxMenu;
1366 Tree::RootHandlerListType::iterator h;
1368 for (h= Tree::GetRootHandlerList().begin();
1369 h!=Tree::GetRootHandlerList().end();
1372 if ((*h)->SupportsNew())
1374 newmenu->Append(PopUp_New+i, std2wx((*h)->GetName()));
1376 if ((*h)->SupportsOpen())
1377 openmenu->Append(PopUp_Open+i, std2wx((*h)->GetName()));
1381 menu.AppendSubMenu(openmenu, _T("&Open"));
1382 menu.AppendSubMenu(newmenu, _T("&New"));
1386 if ((data->IsDatabase())||(data->IsDicomNode()))
1388 Root* itroot = data->GetDicomNode()->GetDicomDatabase();
1389 // if (!itroot) itroot = data->GetDicomNode()->GetRoot();
1390 wxMenu* insertmenu = new wxMenu;
1391 bool hasone = false;
1393 Tree::RootListType::iterator j;
1394 for (j = mTree->GetDatabaseList().begin();
1395 j != mTree->GetDatabaseList().end();
1398 // std::cout << (*j)->GetName() << " "
1399 // << (*j)->GetTypeName()
1400 // << " i="<<(*j)->SupportsInsert()<<std::endl;
1401 if ( ((*j)!=itroot) && ((*j)->SupportsInsert()) )
1403 insertmenu->Append(PopUp_Insert+i,
1404 std2wx((*j)->GetName()));
1410 if (hasone) menu.AppendSubMenu(insertmenu, _T("&Insert into"));
1412 if (data->IsDatabase())
1414 menu.Append(PopUp_Close, wxT("&Close"));
1416 if (data->IsDicomNode() && data->GetDicomNode()->GetDicomDatabase()->SupportsRemove())
1418 menu.Append(PopUp_Remove, wxT("&Remove"));
1426 PopupMenu(&menu, pt);
1427 #endif // wxUSE_MENUS
1429 // std::cout << "EO ShowMenu" <<std::endl;
1431 //=====================================================================
1433 //=====================================================================
1434 // Pop up menu callbacks
1435 void WxGimmick::OnPopUpAbout(wxCommandEvent& event)
1437 wxMessageBox( _T("Give me my medical images quick ! \n\n (c) CREATIS-LRMN 2008\n"),
1439 wxOK | wxICON_INFORMATION, this);
1441 //=====================================================================
1443 //=====================================================================
1444 void WxGimmick::OnPopUpSettings(wxCommandEvent& event)
1446 WxGimmickSettingsDialog* s =
1447 new WxGimmickSettingsDialog(this);
1451 //=====================================================================
1453 //=====================================================================
1454 void WxGimmick::OnPopUpNewCollection(wxCommandEvent& event)
1457 OpenOrNewDatabase(false);
1459 //=====================================================================
1463 //=====================================================================
1464 void WxGimmick::OnPopUpOpenCollection(wxCommandEvent& event)
1467 OpenOrNewDatabase(true);
1469 //=====================================================================
1472 //=====================================================================
1473 void WxGimmick::OnPopUpCloseCollection(wxCommandEvent& event)
1475 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;
1478 // std::cout << "OnPopUpClose"<<std::endl;
1479 // wxTreeItemId id = event.GetId();
1480 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1481 DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
1482 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1483 DeleteDicomDatabase(mItemOfMenu,r);
1485 //=====================================================================
1487 //=====================================================================
1488 void WxGimmick::OnPopUpDeleteCollection(wxCommandEvent& event)
1490 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;
1495 // std::cout << "OnPopUpClose"<<std::endl;
1496 // wxTreeItemId id = event.GetId();
1497 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1498 DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
1500 wxRemoveFile(std2wx(r->GetFileName()));
1501 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1502 DeleteDicomDatabase(mItemOfMenu,r);
1505 //=====================================================================
1507 void DisplayUpdateSummary( DicomDatabase::UpdateSummary& summary,
1510 std::stringstream mess;
1511 mess << "Dirs\tscanned\t\t\t: " << summary.scanned_dirs << "\n";
1512 mess << "Files\tscanned\t\t\t: " << summary.scanned_files << "\n";
1513 mess << "Files\thandled\t\t\t: " << summary.handled_images << "\n\n";
1514 mess << "Patients\tadded\t\t: " << summary.added_patients<< "\n";
1515 mess << "Studies\tadded\t\t: " << summary.added_studies<< "\n";
1516 mess << "Series\tadded\t\t: " << summary.added_series<< "\n";
1517 mess << "Images\tadded\t\t: " << summary.added_images<< "\n\n";
1519 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",
1521 (int)( summary.parse_time*100./summary.total_time),
1522 summary.file_scan_time,
1523 (int)(summary.file_scan_time*100./summary.total_time),
1524 summary.update_structs_time,
1525 (int)(summary.update_structs_time*100./summary.total_time),
1526 summary.update_database_time,
1527 (int)(summary.update_database_time*100./summary.total_time),
1528 summary.total_time );
1532 wxMessageBox(std2wx(mess.str()),_T("Update summary"),wxOK,parent);
1536 //=====================================================================
1537 void WxGimmick::OnPopUpAddFile(wxCommandEvent& event)
1539 long style = wxOPEN | wxFILE_MUST_EXIST | wxFD_MULTIPLE;
1540 std::string wc("*.*");
1541 wxFileDialog* FD = new wxFileDialog( 0,
1549 if (FD->ShowModal()==wxID_OK)
1553 mCurrentDirectory = FD->GetDirectory();
1554 wxArrayString files;
1555 FD->GetPaths(files);
1557 std::vector<std::string> filenames;
1558 for (i=0;i<files.GetCount();++i)
1559 filenames.push_back(wx2std(files[i]));
1562 TreeItemData *data =
1564 mTreeListCtrl->GetItemData(mItemOfMenu);
1565 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1566 DicomDatabase::UpdateSummary summary;
1567 wxProgressDialog* progress =
1568 new wxProgressDialog(_T("Adding file(s)"),
1573 wxPD_ESTIMATED_TIME |
1574 wxPD_REMAINING_TIME |
1577 db->AddFiles(filenames,progress,summary);
1579 progress->Pulse(_T("Updating view..."));
1580 UpdateDicomDatabaseView(db);
1582 DisplayUpdateSummary(summary,this);
1586 //=====================================================================
1588 //=====================================================================
1589 void WxGimmick::OnPopUpAddRawFile(wxCommandEvent& event)
1591 wxMessageBox(_T("Not yet implemented !"),_T("Sorry"),wxOK,this);
1593 //=====================================================================
1595 //=====================================================================
1596 void WxGimmick::OnPopUpAddDirectory(wxCommandEvent& event)
1598 long style = wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST;
1601 _T("Select directory"),
1605 if (FD->ShowModal()==wxID_OK)
1608 bool recurse = false;
1609 if (wxMessageBox(_T("Recurse into sub-directories ?"),
1610 _T("Scan directory"),
1611 wxYES_NO,this ) == wxYES)
1617 wxProgressDialog* progress =
1618 new wxProgressDialog(_T("Scanning directory"),
1619 _T("Parsing directory"),
1623 wxPD_ESTIMATED_TIME |
1624 wxPD_REMAINING_TIME |
1626 DicomDatabase::UpdateSummary summary;
1628 std::string dirname = wx2std (FD->GetPath()) ;
1629 mCurrentDirectory = FD->GetPath();
1630 TreeItemData *data =
1632 mTreeListCtrl->GetItemData(mItemOfMenu);
1633 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1634 db->AddDirectory(dirname,recurse,progress,summary);
1636 progress->Pulse(_T("Updating view..."));
1637 UpdateDicomDatabaseView(db);
1640 DisplayUpdateSummary(summary,this);
1642 if (summary.cancelled_by_user)
1644 std::cout << "!! Cancelled by user !!"<<std::endl;
1650 //=====================================================================
1652 //=====================================================================
1653 void WxGimmick::OnPopUpRemove(wxCommandEvent& event)
1657 wxMessageBox(_T("Not yet implemented"),_T("Sorry !"),wxOK);
1661 // wxTreeItemId id = event.GetId();
1662 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1664 std::string mess("Remove ");
1665 mess += data->GetDicomNode()->GetTypeName();
1666 mess += " from collection ?";
1667 int answer = wxMessageBox(std2wx(mess), _T("Confirm"), wxYES_NO);
1668 if (answer == wxNO) return;
1670 if ( mTreeListCtrl->IsSelected(mItemOfMenu) )
1672 wxTreeItemId next = mTreeListCtrl->GetNextSibling(mItemOfMenu);
1675 mTreeListCtrl->SelectItem(next);
1683 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1684 db->Remove(data->GetDicomNode());
1685 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1686 // TODO : Optimize update only parent's branch
1687 UpdateDicomDatabaseView(db);
1688 // DeleteDicomDatabase(mItemOfMenu,r);
1690 //=====================================================================
1692 //=====================================================================
1693 void WxGimmick::OnPopUpSort(wxCommandEvent& event)
1696 // std::cout << "OnPopUpSort"<<std::endl;
1697 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1698 int index = event.GetId() - PopUp_Sort;
1699 DicomNode* node = data->GetDicomNode();
1700 DicomNode::Type ctype = node->GetType()+1;
1701 mSettings.SetActiveComparatorIndex(ctype,index);
1703 if (node->ChildrenLoaded())
1706 mTreeListCtrl->DeleteChildren(mItemOfMenu);
1708 /* std::cout << "Sorting using '"
1709 << mSettings.GetActiveComparator(ctype).GetName()
1712 node->SortChildren ( mSettings.GetActiveComparator(ctype) );
1713 // std::cout << "ok"<<std::endl;
1717 CreateChildrenColumnsTitles(mItemOfMenu,ctype);
1718 DicomNode::ChildrenListType::iterator i;
1719 for (i=node->GetChildrenList().begin();
1720 i!=node->GetChildrenList().end();
1723 UpdateDicomNodeView(*i,mItemOfMenu);
1727 //=====================================================================
1730 //=====================================================================
1731 void WxGimmick::OnPopUpUser(wxCommandEvent& event)
1733 // std::cout << "OnPopUpUser"<<std::endl;
1736 //=====================================================================
1738 //=================================================
1739 void WxGimmick::CreateImageList(int size)
1743 mTreeListCtrl->SetImageList(NULL);
1752 // should correspond to Icon_xxx enum
1753 icons[Icon_Patient] = wxIcon(patient_xpm);
1754 icons[Icon_Study] = wxIcon(study_xpm);
1755 icons[Icon_Series] = wxIcon(series_xpm);
1756 icons[Icon_Image] = wxIcon(image_xpm);
1757 icons[Icon_Database] = wxIcon(database_xpm);
1758 icons[Icon_Folder] = wxIcon(folder_xpm);
1759 icons[Icon_DicomDir] = wxIcon(dicomdir_xpm);
1760 icons[Icon_Root] = wxIcon(root_xpm);
1763 // mFirstRootIconIndex = 8;
1766 Tree::RootHandlerListType::iterator h;
1768 for (h= Tree::GetDatabaseHandlerList().begin();
1769 h!=Tree::GetDatabaseHandlerList().end();
1772 icons[mFirstRootIconIndex+i] = (*h)->GetIcon();
1776 unsigned int NbIcons = 8;//mFirstRootIconIndex + i;
1777 // Make an image list containing small icons
1778 wxImageList *images = new wxImageList(size, size, true);
1780 int sizeOrig = icons[0].GetWidth();
1781 for ( size_t i = 0; i < NbIcons; i++ )
1783 if ( size == sizeOrig )
1785 images->Add(icons[i]);
1789 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
1792 mTreeListCtrl->AssignImageList(images);
1794 //=================================================
1803 //================================================================
1804 bool WxGimmick::IsImageSelectable(DicomNode* node)
1806 int rows = node->ImageGetRows();
1807 int cols = node->ImageGetColumns();
1808 int frms = node->ImageGetFrames();
1810 // std::cout << "R/C/F = " << rows << "/"<< cols <<"/"<<frms<<std::endl;
1814 else if (cols>0) dim=2;
1815 else if (rows>0) dim=1;
1819 std::cout << "Unknown image dimension : cannot select !"
1823 else if (dim>mSelectionMaxImageDimension)
1825 std::cout << "Selecting "<<dim<<"D images is not allowed !"
1830 if ( mTreeListCtrl->GetSelectionSize() == 0 )
1832 mCurrentSelectionImageSize[0] = cols;
1833 mCurrentSelectionImageSize[1] = rows;
1834 mCurrentSelectionImageSize[2] = frms;
1839 if ( dim == mSelectionMaxImageDimension )
1841 std::cout << "Cannot add this image to selection : would result in a "<<dim+1<<"D image !" << std::endl;
1844 if ( ( cols != mCurrentSelectionImageSize[0] ) ||
1845 ( rows != mCurrentSelectionImageSize[1] ) ||
1846 ( frms != mCurrentSelectionImageSize[2] ) )
1848 std::cout << "Cannot add this image to selection : image size is incomptatible with currently selected images" << std::endl;
1852 // std::cout << "Selecting : "<<node->ImageGetFullFileName() << std::endl;
1855 //================================================================
1857 //================================================================
1858 void WxGimmick::OnSelChanging(wxTreeEvent& event)
1861 wxTreeItemId id = event.GetItem();
1864 std::cout << "INTERNAL ERROR : ID NOT OK"<<std::endl;
1869 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1870 if (data->IsDicomNode())
1872 if (data->GetDicomNode()>0)
1874 // An image was selected
1875 if (data->GetDicomNode()->GetType()==DicomNode::Image)
1877 if (IsImageSelectable(data->GetDicomNode())) event.Allow();
1879 // A series was selected
1880 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
1882 // If images not loaded do it
1884 // can be selected if all its images can
1886 wxTreeItemIdValue cookie;
1887 for (child = mTreeListCtrl->GetFirstChild(id,cookie);
1889 child = mTreeListCtrl->GetNextChild(id,cookie))
1891 TreeItemData *cdata =
1892 (TreeItemData *)mTreeListCtrl->GetItemData(child);
1893 if ((cdata->IsDicomNode())&&
1894 (cdata->GetDicomNode()>0)&&
1895 (cdata->GetDicomNode()->GetType()==DicomNode::Image)&&
1896 (!IsImageSelectable(cdata->GetDicomNode())))
1904 //================================================================
1906 //================================================================
1907 void WxGimmick::OnSelChanged(wxTreeEvent& event)
1909 // wxBusyCursor busy;
1910 // std::vector<wxTreeItemId> items;
1911 // GetSelectedItems(items);
1913 std::vector<DicomNode*>::iterator i;
1914 for (i=nodes.begin();i!=nodes.end();++i)
1916 std::cout << "'" << (*i)->GetFieldValue("FullFileName")
1917 << "'" << std::endl;
1919 std::cout << "++++++++++++++++++++" << std::endl;
1921 // ShowImage(mReader.GetImage(""));
1923 bool no_image = true;
1925 static int max = 1000;
1928 // if (items.size()>0)
1931 // Update image preview : send requests to the MTImageReader
1932 // bool first = true;
1933 // std::vector<wxTreeItemId>::iterator i;
1934 // for (i=items.begin();i!=items.end();++i)
1940 DicomNode* node = GetDicomNodeOfItem(items[0]);
1942 // Update dicom fields panel
1943 mFieldsView->UpdateValues(node);
1947 wxTreeItemId item = mTreeListCtrl->GetCurrent();
1949 DicomNode* n = GetDicomNodeOfItem(item);
1951 if (n) mFieldsView->UpdateValues(n);
1954 (n->GetType()==DicomNode::Image) )
1959 //if (i==items.begin())
1960 mCurImageItemToShow = item;
1962 int maxprio = mReader.GetMaximalPriority();
1963 int prio = maxprio + 1000;
1964 wxTreeItemId sib = item; //GetTreeListCtrl()->GetNextSibling(*i);
1967 DicomNode* nsib = GetDicomNodeOfItem(sib);
1970 // std::cout << "-- Request '"
1971 // << nsib->GetFieldValue("FullFileName")
1972 // << "' prio="<<prio<<std::endl;
1973 mReader.Request(this,
1974 nsib->ImageGetFullFileName(),
1976 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
1980 sib = GetTreeListCtrl()->GetNextSibling(sib);
1982 prio = maxprio + 1000;
1983 sib = GetTreeListCtrl()->GetPrevSibling(item);
1986 DicomNode* nsib = GetDicomNodeOfItem(sib);
1989 // std::cout << "-- Request '"
1990 // << nsib->GetFieldValue("FullFileName")
1991 // << "' prio="<<prio<<std::endl;
1992 mReader.Request(this,
1993 nsib->ImageGetFullFileName(),
1995 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
1999 sib = GetTreeListCtrl()->GetPrevSibling(sib);
2001 // mImageFileNameToNode[n->GetFieldValue("FullFileName")] = n;
2004 ProcessImageEvents();
2006 // std::cout << "* Selection changed * (im)"<<std::endl;
2008 //---------------------------------------------------------------------
2010 WxGimmickEvent ev(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED,
2014 GetEventHandler()->ProcessEvent(ev);
2016 if (no_image) ShowImage(mReader.GetImage(""));
2019 //================================================================
2021 //================================================================
2022 void WxGimmick::ShowImage(vtkImageData* im)
2024 // wxBusyCursor busy;
2026 int x1,x2,y1,y2,z1,z2;
2028 im->GetSpacing(spx,spy,spz);
2029 im->GetExtent (x1,x2,y1,y2,z1,z2);
2032 std::cout << x1 << "-"<<x2<<std::endl;
2033 std::cout << y1 << "-"<<y2<<std::endl;
2034 std::cout << z1 << "-"<<z2<<std::endl;
2035 std::cout << spx << "-"<<spy<<"-"<<spz<<std::endl;
2059 vtkCamera *camera = mViewer->GetRenderer()->GetActiveCamera();
2061 camera->SetViewUp ( spx*0, -spy*1, spz*0);
2062 camera->SetPosition( spx*(x1+x2)/2, spy*(y1+y2)/2, -spz*10000000);
2063 camera->SetFocalPoint ( spx*(x1+x2)/2 , spy*(y1+y2)/2 , spz*0);
2065 camera->ComputeViewPlaneNormal();
2066 camera->SetParallelScale( spx*(x2-x1)/2.0 );
2070 mViewer->SetInput( im );
2071 mViewer->SetSlice( 0 );
2072 mInteractor->Render();
2074 //================================================================
2081 //================================================================
2083 OnMultiThreadImageReaderEvent(const std::string& filename,
2084 MultiThreadImageReaderUser::EventType e,
2085 vtkImageData* image)
2087 if (filename.size()==0)
2089 mImageEventQueue.push_back(ImageEventType(image));
2092 std::map<std::string,DicomNode*>::iterator i;
2093 i = mImageFileNameToNode.find(filename);
2094 if (i!=mImageFileNameToNode.end())
2096 wxTreeItemId id = i->second->GetData<NodeData*>()->GetTreeItemData()->GetItemId();
2097 mImageEventQueue.push_back(ImageEventType(id,image));
2100 //================================================================
2102 //================================================================
2103 // Processes the queue of image events
2104 void WxGimmick::ProcessImageEvents()
2106 // std::cout << "++++++++++ ProcessImageEvents " << std::endl;
2107 MultiThreadImageReaderEventLock();
2110 while (!mImageEventQueue.empty())
2112 ImageEventType e = mImageEventQueue.front();
2113 mImageEventQueue.pop_front();
2118 mTreeListCtrl->SetItemTextColour(e.item,
2119 mSettings.LoadedImageColour());//wxImageLoadedColour);
2120 TreeItemData *data =
2121 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2122 data->SetLoaded(true);
2124 if (mCurImageItemToShow == e.item)
2129 else if (!mCurImageItemToShow.IsOk())
2134 else if (e.item.IsOk())
2136 mTreeListCtrl->SetItemTextColour(e.item,mSettings.Colour(DicomNode::Image)); //.wxImageUnloadedColour);
2137 TreeItemData *data =
2138 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2139 data->SetLoaded(false);
2142 mImageEventQueue.clear();
2143 MultiThreadImageReaderEventUnlock();
2144 // std::cout << "++++++++++ END ProcessImageEvents " << std::endl;
2146 //================================================================
2148 //================================================================
2149 void WxGimmick::OnInternalIdle()
2151 ProcessImageEvents();
2153 //================================================================
2156 //================================================================
2157 // LG : For the moment any selection is valid but in the future
2158 // incomplete selections can be invalid...
2159 bool WxGimmick::IsSelectionValid()
2161 return (mTreeListCtrl->GetSelectionSize()>0);
2163 //================================================================
2165 //================================================================
2166 void WxGimmick::GetSelectedFiles(std::vector<std::string>& f)
2168 wxArrayTreeItemIds id;
2169 // TO DO : TEST THAT STYLE IS MULTIPLE
2170 unsigned int nb = mTreeListCtrl->GetSelections(id);
2172 for (unsigned int i=0; i<nb; ++i)
2174 TreeItemData *data =
2175 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2176 if ((data) && (data->IsDicomNode()))
2178 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2180 f.push_back ( data->GetDicomNode()->ImageGetFullFileName() );
2182 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2184 DicomNode::ChildrenListType::iterator j;
2185 for (j =data->GetDicomNode()->GetChildrenList().begin();
2186 j!=data->GetDicomNode()->GetChildrenList().end();
2189 f.push_back((*j)->ImageGetFullFileName());
2195 //================================================================
2197 //================================================================
2198 void WxGimmick::GetSelectedImages(std::vector<vtkImageData*>& f)
2200 wxArrayTreeItemIds id;
2201 // TO DO : TEST THAT STYLE IS MULTIPLE
2202 unsigned int nb = mTreeListCtrl->GetSelections(id);
2205 // Collect the brute vector of Image nodes
2206 std::vector<DicomNode*> im;
2207 for (unsigned int i=0; i<nb; ++i)
2209 TreeItemData *data =
2210 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2211 if ((data) && (data->IsDicomNode()))
2213 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2215 im.push_back ( data->GetDicomNode() );
2218 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2220 DicomNode::ChildrenListType::iterator j;
2221 for (j =data->GetDicomNode()->GetChildrenList().begin();
2222 j!=data->GetDicomNode()->GetChildrenList().end();
2225 im.push_back ( *j );
2230 // Create the output data
2233 // Only one image : give it
2234 vtkImageData* out = vtkImageData::New();
2235 out->ShallowCopy(mReader.GetImage(im.front()->ImageGetFullFileName()));
2238 else if (im.size()>1)
2240 vtkImageData* first = mReader.GetImage( im.front()->ImageGetFullFileName() );
2241 if (first->GetDataDimension()==2)
2244 vtkImageData* out = vtkImageData::New();
2245 out->CopyStructure(first);
2246 out->SetScalarType(first->GetScalarType());
2248 first->GetExtent(ext);
2250 out->SetExtent(ext);
2251 // LG : TODO : Z Spacing ?
2253 out->AllocateScalars();
2255 //first->Print(std::cout);
2256 // out->Print(std::cout);
2259 first->GetDimensions(dim);
2260 unsigned long imsize =
2261 ( (unsigned long)first->GetScalarPointer(0,1,0)
2262 - (unsigned long)first->GetScalarPointer(0,0,0))
2266 std::vector<DicomNode*>::iterator it;
2267 for (it=im.begin(); it!=im.end(); ++it)
2269 //std::cout << "copying slice "<<slice <<std::endl;
2270 vtkImageData* cur = mReader.GetImage( (*it)->ImageGetFullFileName() );
2272 void* src = cur->GetScalarPointer(0,0,0);
2273 void* dst = out->GetScalarPointer(0,0,slice);
2274 // std::cout << "src="<<src<<std::endl;
2275 // std::cout << "dst="<<dst<<std::endl;
2276 // std::cout << "siz="<<imsize<<std::endl;
2277 memcpy(dst,src,imsize);
2282 for (ii=1;ii<4;ii++) {
2283 for (jj=1;jj<4;jj++) {
2284 int x = (int)(ii*dim[0] / 4);
2285 int y = (int)(jj*dim[1] / 4);
2286 std::cout << cur->GetScalarComponentAsFloat(x,y,0,0)
2288 << out->GetScalarComponentAsFloat(x,y,slice,0)
2301 std::vector<DicomNode*>::iterator it;
2302 for (it=im.begin(); it!=im.end(); ++it)
2304 vtkImageData* out = vtkImageData::New();
2305 out->ShallowCopy(mReader.GetImage((*it)->ImageGetFullFileName()));
2311 //================================================================
2314 //================================================================
2315 void WxGimmick::GetSelectedDicomNodes(std::vector<DicomNode*>& f)
2317 wxArrayTreeItemIds id;
2318 // TO DO : TEST THAT STYLE IS MULTIPLE
2319 unsigned int nb = mTreeListCtrl->GetSelections(id);
2321 for (unsigned int i=0; i<nb; ++i)
2323 TreeItemData *data =
2324 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2325 if ((data) && (data->IsDicomNode()))
2327 f.push_back ( data->GetDicomNode() );
2331 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2333 f.push_back ( data->GetDicomNode() ); //->ImageGetFullFileName() );
2335 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2337 DicomNode::ChildrenListType::iterator j;
2338 for (j =data->GetDicomNode()->GetChildrenList().begin();
2339 j!=data->GetDicomNode()->GetChildrenList().end();
2342 f.push_back((*j)); //->ImageGetFullFileName() ); }
2348 //================================================================
2350 //================================================================
2351 void WxGimmick::GetSelectedItems(std::vector<wxTreeItemId>& f)
2353 wxArrayTreeItemIds id;
2354 // TO DO : TEST THAT STYLE IS MULTIPLE
2355 unsigned int nb = mTreeListCtrl->GetSelections(id);
2357 for (unsigned int i=0; i<nb; ++i)
2362 //================================================================
2364 //================================================================
2365 DicomNode* WxGimmick::GetDicomNodeOfItem(const wxTreeItemId& i)
2367 TreeItemData *data =
2368 (TreeItemData *)mTreeListCtrl->GetItemData(i);
2369 if (data) return ( data->GetDicomNode() );
2372 //================================================================
2374 //================================================================
2375 //================================================================
2376 //================================================================
2377 //================================================================
2393 //================================================================
2394 //================================================================
2395 //================================================================
2396 //================================================================
2398 BEGIN_EVENT_TABLE(WxGimmick, wxPanel)
2400 EVT_MENU(PopUp_NewCollection,WxGimmick::OnPopUpNewCollection)
2401 EVT_MENU(PopUp_OpenCollection,WxGimmick::OnPopUpOpenCollection)
2402 EVT_MENU(PopUp_CloseCollection,WxGimmick::OnPopUpCloseCollection)
2403 EVT_MENU(PopUp_DeleteCollection,WxGimmick::OnPopUpDeleteCollection)
2404 EVT_MENU(PopUp_AddFile, WxGimmick::OnPopUpAddFile)
2405 EVT_MENU(PopUp_AddRawFile, WxGimmick::OnPopUpAddRawFile)
2406 EVT_MENU(PopUp_AddDirectory, WxGimmick::OnPopUpAddDirectory)
2407 EVT_MENU(PopUp_Remove, WxGimmick::OnPopUpRemove)
2408 EVT_MENU(PopUp_About, WxGimmick::OnPopUpAbout)
2409 EVT_MENU(PopUp_Settings, WxGimmick::OnPopUpSettings)
2411 EVT_MENU_RANGE(PopUp_Sort, PopUp_Sort+99, WxGimmick::OnPopUpSort)
2412 EVT_MENU_RANGE(PopUp_User, PopUp_User+99, WxGimmick::OnPopUpUser)
2417 EVT_TREE_BEGIN_DRAG(TreeListCtrlId, WxGimmick::OnBeginDrag)
2418 EVT_TREE_BEGIN_RDRAG(TreeListCtrlId, WxGimmick::OnBeginRDrag)
2419 EVT_TREE_END_DRAG(TreeListCtrlId, WxGimmick::OnEndDrag)
2422 EVT_TREE_BEGIN_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnBeginLabelEdit)
2423 EVT_TREE_END_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnEndLabelEdit)
2426 EVT_TREE_DELETE_ITEM(TreeListCtrlId, WxGimmick::OnDeleteItem)
2427 #if 0 // there are so many of those that logging them causes flicker
2428 EVT_TREE_GET_INFO(TreeListCtrlId, WxGimmick::OnGetInfo)
2431 EVT_TREE_SET_INFO(TreeListCtrlId, WxGimmick::OnSetInfo)
2434 EVT_TREE_ITEM_EXPANDED(TreeListCtrlId, WxGimmick::OnItemExpanded)
2435 EVT_TREE_ITEM_EXPANDING(TreeListCtrlId, WxGimmick::OnItemExpanding)
2436 EVT_TREE_ITEM_COLLAPSED(TreeListCtrlId, WxGimmick::OnItemCollapsed)
2437 EVT_TREE_ITEM_COLLAPSING(TreeListCtrlId, WxGimmick::OnItemCollapsing)
2440 EVT_TREE_SEL_CHANGED(TreeListCtrlId, WxGimmick::OnSelChanged)
2441 EVT_TREE_SEL_CHANGING(TreeListCtrlId, WxGimmick::OnSelChanging)
2443 EVT_TREE_KEY_DOWN(TreeListCtrlId, WxGimmick::OnTreeKeyDown)
2444 // ACTIVATION = DOUBLE CLICK OR ENTER ON SELECTED
2445 EVT_TREE_ITEM_ACTIVATED(TreeListCtrlId, WxGimmick::OnItemActivated)
2447 // so many differents ways to handle right mouse button clicks...
2448 // EVT_CONTEXT_MENU(WxGimmick::OnContextMenu)
2449 // EVT_TREE_ITEM_MENU is the preferred event for creating context menus
2450 // on a tree control, because it includes the point of the click or item,
2451 // meaning that no additional placement calculations are required.
2452 // EVT_TREE_ITEM_MENU(TreeListCtrlId, WxGimmick::OnItemMenu)
2454 EVT_TREE_ITEM_RIGHT_CLICK(TreeListCtrlId, WxGimmick::OnItemRightClick)
2457 // EVT_RIGHT_DOWN(WxGimmick::OnRMouseDown)
2458 // EVT_RIGHT_UP(WxGimmick::OnRMouseUp)
2459 // EVT_RIGHT_DCLICK(WxGimmick::OnRMouseDClick)
2462 //IMPLEMENT_DYNAMIC_CLASS(WxGimmick, wxTreeListCtrl)
2465 wxTree::wxTree(wxWindow *parent, const wxWindowID id,
2466 const wxPoint& pos, const wxSize& size,
2468 : wxTreeListCtrl(parent, id, pos, size, style)
2470 m_reverseSort = false;
2474 // Add some items to the tree
2475 AddTestItemsToTree(5, 2);
2481 #if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
2482 void WxGimmick::CreateButtonsImageList(int size)
2487 mTreeListCtrl->SetButtonsImageList(NULL);
2491 // Make an image list containing small icons
2492 wxImageList *images = new wxImageList(size, size, true);
2494 // should correspond to TreeListCtrlIcon_xxx enum
2497 icons[0] = wxIcon(icon3_xpm); // closed
2498 icons[1] = wxIcon(icon3_xpm); // closed, selected
2499 icons[2] = wxIcon(icon5_xpm); // open
2500 icons[3] = wxIcon(icon5_xpm); // open, selected
2502 for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
2504 int sizeOrig = icons[i].GetWidth();
2505 if ( size == sizeOrig )
2507 images->Add(icons[i]);
2511 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
2515 mTreeListCtrl->AssignButtonsImageList(images);
2518 void WxGimmick::CreateButtonsImageList(int WXUNUSED(size))
2524 int WxGimmick::OnCompareItems(const wxTreeItemId& item1,
2525 const wxTreeItemId& item2)
2527 if ( m_reverseSort )
2529 // just exchange 1st and 2nd items
2530 return mTreeListCtrl->OnCompareItems(item2, item1);
2534 return mTreeListCtrl->OnCompareItems(item1, item2);
2539 void WxGimmick::DoToggleIcon(const wxTreeItemId& item)
2542 int image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_Folder)
2545 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Normal);
2547 image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_FolderSelected)
2548 ? TreeIcon_FileSelected
2549 : TreeIcon_FolderSelected;
2550 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Selected);
2553 void WxGimmick::LogEvent(const wxChar *name, const wxTreeEvent& event)
2555 wxTreeItemId item = event.GetItem();
2558 text << _T('"') << mTreeListCtrl->GetItemText(item).c_str() << _T('"');
2560 text = _T("invalid item");
2561 // wxLogMessage(wxT("%s(%s)"), name, text.c_str());
2566 #define TREE_EVENT_HANDLER(name) \
2567 void WxGimmick::name(wxTreeEvent& event) \
2569 /* LogEvent(_T(#name), event); */ \
2570 /* SetLastItem(mTreeListCtrl->wxTreeItemId()) *;*/ \
2574 TREE_EVENT_HANDLER(OnBeginRDrag)
2575 TREE_EVENT_HANDLER(OnDeleteItem)
2576 TREE_EVENT_HANDLER(OnGetInfo)
2577 TREE_EVENT_HANDLER(OnSetInfo)
2578 //TREE_EVENT_HANDLER(OnItemExpanded)
2579 TREE_EVENT_HANDLER(OnItemExpanding)
2580 //TREE_EVENT_HANDLER(OnItemCollapsed)
2581 //TREE_EVENT_HANDLER(OnSelChanged)
2582 // TREE_EVENT_HANDLER(OnSelChanging)
2585 void WxGimmick::OnItemCollapsed(wxTreeEvent& event)
2587 // std::cout << "* Collapsed *"<<std::endl;
2590 #undef TREE_EVENT_HANDLER
2592 void WxGimmick::OnTreeKeyDown(wxTreeEvent& event)
2595 // LogKeyEvent(wxT("Tree key down "), event.GetKeyEvent());
2596 std::cout << "* Key down *"<<std::endl;
2597 if (event.GetKeyCode()==WXK_RIGHT)
2599 std::cout << "Right"<<std::endl;
2600 wxTreeItemId itemId = mTreeListCtrl->GetSelection();
2603 std::cout << "item is ok"<<std::endl;
2604 wxPoint clientpt = event.GetPoint();
2605 wxPoint screenpt = ClientToScreen(clientpt);
2606 ShowMenu(itemId, clientpt);
2611 std::cout << "NOT Right"<<std::endl;
2616 void WxGimmick::OnBeginDrag(wxTreeEvent& event)
2618 wxTreeItemId id = event.GetItem();
2619 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2620 // std::cout << "OnBeginDrag("<<id<<")"<<std::endl;
2621 if (data->IsDatabase())
2623 // std::cout << "-- IS ROOT"<<std::endl;
2626 else if (data->IsDicomNode())
2628 // std::cout << "-- IS NODE"<<std::endl;
2631 // need to explicitly allow drag
2632 if ( event.GetItem() != GetDatabaseItem() )
2634 m_draggedItem = event.GetItem();
2636 wxPoint clientpt = event.GetPoint();
2637 wxPoint screenpt = ClientToScreen(clientpt);
2639 wxLogMessage(wxT("OnBeginDrag: started dragging %s at screen coords (%i,%i)"),
2640 GetItemText(m_draggedItem).c_str(),
2641 screenpt.x, screenpt.y);
2647 wxLogMessage(wxT("OnBeginDrag: this item can't be dragged."));
2652 void WxGimmick::OnEndDrag(wxTreeEvent& event)
2654 wxTreeItemId id = event.GetItem();
2655 // std::cout << "OnEndDrag("<<id<<")"<<std::endl;
2656 if (!id.IsOk()) return;
2657 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2658 if (data->IsDatabase())
2660 // std::cout << "-- IS ROOT"<<std::endl;
2662 else if (data->IsDicomNode())
2664 // std::cout << "-- IS NODE"<<std::endl;
2668 wxTreeItemId itemSrc = m_draggedItem,
2669 itemDst = event.GetItem();
2670 m_draggedItem = (wxTreeItemId)0l;
2672 // where to copy the item?
2673 if ( itemDst.IsOk() && !ItemHasChildren(itemDst) )
2675 // copy to the parent then
2676 itemDst = GetItemParent(itemDst);
2679 if ( !itemDst.IsOk() )
2681 wxLogMessage(wxT("OnEndDrag: can't drop here."));
2686 wxString text = GetItemText(itemSrc);
2687 wxLogMessage(wxT("OnEndDrag: '%s' copied to '%s'."),
2688 text.c_str(), GetItemText(itemDst).c_str());
2690 // just do append here - we could also insert it just before/after the item
2691 // on which it was dropped, but this requires slightly more work... we also
2692 // completely ignore the client data and icon of the old item but could
2693 // copy them as well.
2695 // Finally, we only copy one item here but we might copy the entire tree if
2696 // we were dragging a folder.
2697 int image = wxGetApp().ShowImages() ? TreeIcon_File : -1;
2698 AppendItem(itemDst, text, image);
2703 //====================================================================
2704 void WxGimmick::OnBeginLabelEdit(wxTreeEvent& event)
2706 // std::cout << "OnBeginLabelEdit"<<std::endl;
2707 wxTreeItemId id = event.GetItem();
2708 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2709 // If not a root : veto
2710 if (data->IsDatabase())
2717 //====================================================================
2719 //====================================================================
2720 void WxGimmick::OnEndLabelEdit(wxTreeEvent& event)
2722 // std::cout << "OnEndLabelEdit"<<std::endl;
2723 wxTreeItemId id = event.GetItem();
2724 TreeItemData *data = GetItemData(id);
2725 // If not a database : bug !
2726 if (data->IsDatabase())
2728 data->GetDicomNode()->GetDicomDatabase()->SetName(wx2std(event.GetLabel()));
2729 mFieldsView->UpdateValues(data->GetDicomNode());
2733 std::cerr<< "!!!! Internal error : send bug report !!!!"<<std::endl;
2736 //====================================================================
2739 void WxGimmick::OnItemCollapsing(wxTreeEvent& event)
2741 // wxLogMessage(wxT("OnItemCollapsing"));
2743 // for testing, prevent the user from collapsing the first child folder
2744 wxTreeItemId itemId = event.GetItem();
2747 if ( IsTestItem(itemId) )
2749 wxMessageBox(wxT("You can't collapse this item."));
2766 //================================================================
2767 //================================================================
2768 //================================================================
2769 //================================================================
2770 //================================================================
2772 //================================================================
2773 //================================================================
2774 //================================================================
2775 //================================================================
2776 //================================================================
2782 // ----------------------------------------------------------------------------
2784 // ----------------------------------------------------------------------------
2786 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_DRAG)
2787 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_RDRAG)
2788 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_DELETE_ITEM)
2789 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_GET_INFO)
2790 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SET_INFO)
2791 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDED)
2792 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDING)
2793 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSED)
2794 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSING)
2797 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT)
2798 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_LABEL_EDIT)
2801 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED)
2802 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGING)
2803 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_KEY_DOWN)
2804 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU)
2805 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_ITEM_STYLE_CHANGED)
2807 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_ACTIVATED)
2808 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK)
2809 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK)
2810 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_DRAG)
2811 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK)
2812 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP)
2813 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MENU)
2815 // ----------------------------------------------------------------------------
2817 // ----------------------------------------------------------------------------
2819 IMPLEMENT_ABSTRACT_CLASS(WxGimmickEvent, wxNotifyEvent)
2822 WxGimmickEvent::WxGimmickEvent(wxEventType commandType,
2824 const wxTreeItemId& item)
2826 wxNotifyEvent(commandType, tree->GetId()),
2830 // m_editCancelled = false;
2832 SetEventObject(tree);
2835 SetClientObject(tree->mTreeListCtrl->GetItemData(item));
2838 WxGimmickEvent::WxGimmickEvent(wxEventType commandType, int id)
2840 wxNotifyEvent(commandType, id),
2844 // m_editCancelled = false;
2847 WxGimmickEvent::WxGimmickEvent(const WxGimmickEvent & event)
2849 wxNotifyEvent(event),
2853 m_evtKey = event.m_evtKey;
2854 m_item = event.m_item;
2855 m_itemOld = event.m_itemOld;
2856 mColor = event.mColor;
2857 mUserData = event.mUserData;
2858 // m_pointDrag = event.m_pointDrag;
2859 // m_label = event.m_label;
2860 // m_editCancelled = event.m_editCancelled;
2870 //================================================================
2871 //================================================================
2872 //================================================================
2873 //================================================================
2874 //================================================================
2875 WxGimmickFrame::WxGimmickFrame( wxWindow *parent,
2878 : wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size)
2880 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
2881 mWxGimmick = new WxGimmick(this,-1,
2884 sizer->Add(mWxGimmick,1,wxGROW);
2886 SetAutoLayout(true);
2889 //================================================================
2891 //================================================================
2892 WxGimmickFrame::~WxGimmickFrame()
2895 //================================================================
2897 //================================================================
2898 void WxGimmickFrame::OnSelChanged(WxGimmickEvent& event)
2900 // std::cout << "+++++ WxGimmickFrame::OnSelChanged ++++++++++"
2902 std::vector<std::string> file;
2903 // mWxGimmick->GetSelectedImages(file);
2905 std::vector<std::string>::iterator i;
2906 for (i=file.begin();i!=file.end();++i)
2908 std::cout << "'" << *i << "'" << std::endl;
2910 std::cout << "++++++++++++++++++++" << std::endl;
2913 //================================================================
2915 //================================================================
2916 BEGIN_EVENT_TABLE(WxGimmickFrame, wxFrame)
2917 EVT_TREEVIEWLIST_SEL_CHANGED(-1,WxGimmickFrame::OnSelChanged)
2919 //================================================================
2942 //================================================================
2943 //================================================================
2944 //================================================================
2945 //================================================================
2947 //================================================================
2948 WxGimmickSettingsDialog::WxGimmickSettingsDialog(wxWindow *parent)
2964 //================================================================
2966 //================================================================
2967 WxGimmickSettingsDialog::~WxGimmickSettingsDialog()
2970 //================================================================