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 if ( ! boost::filesystem::remove(filepath) )
864 wxMessageBox(_T("Could not overwrite ")
865 +std2wx(filepath.string()),
874 DicomDatabase* db = new DicomDatabase(filename);
881 wxMessageBox(_T("An error occured while opening ")
891 wxGetTextFromUser(_T("Enter collection name"),_T("New collection"),
893 db->SetName(wx2std(collname));
898 wxMessageBox(_T("An error occured while creating ")
906 GetDicomDatabaseList().push_back(db);
907 UpdateDicomDatabaseView(db);
910 //================================================================
913 //================================================================
914 void WxGimmick::LoadConfiguration()
917 // std::cout << "WxGimmick : Reading config"<<std::endl;
919 // std::cout << "==> Loading collections from '"<<mDatabaseListFile
923 s.open(mDatabaseListFile.c_str());
930 if (str.size()==0) continue;
932 std::vector<std::string> tokens;
933 boost::split( tokens, str, boost::is_any_of("\t") );
935 DicomDatabase* db = new DicomDatabase(tokens[0]);
937 // std::cout << " -> Loading collection '"<<tokens[0]<<"'"<<std::endl;
939 if (tokens.size()==2)
941 db->SetName(tokens[1]);
946 GetDicomDatabaseList().push_back(db);
947 db->DBLoadChildren(db,DicomNode::Patient);
948 if (mSettings.HasActiveComparator(DicomNode::Patient))
951 ( mSettings.GetActiveComparator(DicomNode::Patient) );
956 // std::cout << " ... ERROR !"<<std::endl;
964 std::cout << "ERROR opening "<<mDatabaseListFile<<std::endl;
968 mTreeListCtrl->SetBackgroundColour(mSettings.BgColour(DicomNode::Database));
969 if (GetDicomDatabaseList().begin() !=
970 GetDicomDatabaseList().end() )
972 mFieldsView->UpdateFields(*GetDicomDatabaseList().begin());
978 //================================================================
980 //================================================================
981 void WxGimmick::SaveConfiguration()
984 creaMessage("Gimmick!",1,"Gimmick! : Saving configuration..."<<std::endl);
986 creaMessage("Gimmick!",1,"Gimmick! : ==> Saving collections in '"
987 <<mDatabaseListFile<<"'"<<std::endl);
990 s.open(mDatabaseListFile.c_str());
993 creaError("Gimmick! : error opening '"<<mDatabaseListFile<<"'");
996 DicomDatabaseListType::iterator i;
997 for (i =GetDicomDatabaseList().begin();
998 i!=GetDicomDatabaseList().end();
1001 s << (*i)->GetFileName() << "\t";
1002 s << (*i)->GetName() << std::endl;
1008 //================================================================
1011 //================================================================
1012 void WxGimmick::OnClose(wxCloseEvent& event)
1014 if (mSaveConfigurationOnClose) SaveConfiguration();
1016 //================================================================
1018 //================================================================
1019 void WxGimmick::OnItemActivated(wxTreeEvent& event)
1025 // std::cout << "OnItemActivated" <<std::endl;
1026 wxTreeItemId itemId = event.GetItem();
1027 if (mTreeListCtrl->IsExpanded(itemId))
1029 mTreeListCtrl->Collapse(itemId);
1033 mTreeListCtrl->Expand(itemId);
1036 //================================================================
1038 //================================================================
1039 void WxGimmick::LoadChildren(wxTreeItemId& id)
1041 TreeItemData *item = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1044 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1045 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1048 // If children not already loaded : do it
1050 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1051 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1054 // Some new children loaded
1056 if (mSettings.HasActiveComparator
1057 (item->GetDicomNode()->GetType()+1))
1059 /* std::cout << "Sorting using '"
1060 << mSettings.GetActiveComparator
1061 (item->GetDicomNode()->GetType()+1).GetName()
1064 item->GetDicomNode()->SortChildren
1065 ( mSettings.GetActiveComparator
1066 (item->GetDicomNode()->GetType()+1)
1068 // std::cout << "ok"<<std::endl;
1071 DicomNode::ChildrenListType::iterator i;
1072 for (i=item->GetDicomNode()->GetChildrenList().begin();
1073 i!=item->GetDicomNode()->GetChildrenList().end();
1076 UpdateDicomNodeView(*i,id);
1079 // EO If children not already loaded
1083 //================================================================
1086 //================================================================
1087 void WxGimmick::OnItemExpanded(wxTreeEvent& event)
1090 // std::cout << "* Expanded *"<<std::endl;
1095 wxTreeItemId itemId = event.GetItem();
1096 LoadChildren(itemId);
1100 // expand if collapsed and collapse if expanded ...
1101 TreeItemData *item =
1102 (TreeItemData *)mTreeListCtrl->GetItemData(itemId);
1105 if ( ( item->IsDicomNode() || item->IsDatabase() ) &&
1106 ( ! item->GetDicomNode()->ChildrenLoaded() ) )
1109 // If children not already loaded : do it
1111 item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren
1112 (item->GetDicomNode(),item->GetDicomNode()->GetType()+1)
1116 // Some new children loaded
1118 if (mSettings.HasActiveComparator
1119 (item->GetDicomNode()->GetType()+1))
1121 /* std::cout << "Sorting using '"
1122 << mSettings.GetActiveComparator
1123 (item->GetDicomNode()->GetType()+1).GetName()
1126 item->GetDicomNode()->SortChildren
1127 ( mSettings.GetActiveComparator
1128 (item->GetDicomNode()->GetType()+1)
1130 // std::cout << "ok"<<std::endl;
1133 // If images : sort them
1134 if (item->IsDicomNode())
1136 if (item->GetDicomNode()->GetType()==DicomNode::Series)
1140 LexicographicalDicomNodeComparator compare;
1141 // DicomNodeImageImageNumberComparator c1;
1143 DicomNodeImageSliceLocationComparator c1;
1144 DicomNodeImageImageNumberComparator c2;
1145 DicomNodeImageFileNameComparator cn;
1149 // std::cout << "SORT"<<std::endl;
1150 item->GetDicomNode()->SortChildren(compare);
1151 // std::cout << "EO SORT"<<std::endl;
1159 DicomNode::ChildrenListType::iterator i;
1160 for (i=item->GetDicomNode()->GetChildrenList().begin();
1161 i!=item->GetDicomNode()->GetChildrenList().end();
1164 UpdateDicomNodeView(*i,itemId);
1167 // EO If children not already loaded
1170 // mTreeListCtrl->Expand(itemId);
1173 //================================================================
1177 //=====================================================================
1178 void WxGimmick::InsertRoot(wxTreeItemId& id, Root* r)
1181 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1186 data->GetDicomNode()->GetDicomDatabase()->LoadAll();
1187 printf(">>>>>> Time to load all = %ldms \n",sw.Time());
1189 UpdateRootView(data->GetDicomNode()->GetDicomDatabase());
1192 if (data->IsDicomNode())
1195 r->Insert(data->GetDicomNode());
1196 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1199 else if (data->IsDatabase())
1202 DicomNode::ChildrenListType::iterator j;
1203 for (j= data->GetDicomNode()->GetChildrenList().begin();
1204 j!=data->GetDicomNode()->GetChildrenList().end();
1209 printf(">>>>>> Time to insert = %ldms \n",sw1.Time());
1215 //=====================================================================
1219 //=================================================
1220 void WxGimmick::DeleteDicomDatabase(wxTreeItemId& id,
1224 DicomDatabaseListType::iterator i = find(GetDicomDatabaseList().begin(),
1225 GetDicomDatabaseList().end(),
1228 GetDicomDatabaseList().erase(i);
1229 mTreeListCtrl->Delete(id);
1231 //=================================================
1235 //=====================================================================
1237 void WxGimmick::OnItemRightClick(wxTreeEvent& event)
1240 wxTreeItemId itemId = event.GetItem();
1243 wxPoint clientpt = event.GetPoint();
1244 wxPoint screenpt = ClientToScreen(clientpt);
1245 ShowMenu(itemId, clientpt);
1249 //=====================================================================
1253 //=====================================================================
1254 void WxGimmick::ShowMenu(wxTreeItemId id, const wxPoint& pt)
1257 // std::cout << "ShowMenu" <<std::endl;
1259 TreeItemData *data =
1260 (TreeItemData *)mTreeListCtrl->GetItemData(id);
1266 title << wxT("Menu for ") << mTreeListCtrl->GetItemText(id);
1270 title = wxT("Menu for no particular item");
1277 if (id==mCollectionsTitlesItemId)
1279 menu.Append(PopUp_NewCollection, _T("&New collection"));
1280 menu.Append(PopUp_OpenCollection, _T("&Open collection"));
1284 if (data->IsDatabase())
1286 wxMenu* addmenu = new wxMenu;
1287 addmenu->Append(PopUp_AddDirectory, _T("Scan &Directory"));
1288 addmenu->Append(PopUp_AddFile, _T("Select &File(s)"));
1289 // addmenu->Append(PopUp_AddRawFile, _T("Add &Raw image"));
1290 menu.AppendSubMenu(addmenu, _T("&Add image(s) to collection..."));
1291 menu.Append(PopUp_CloseCollection, _T("&Close collection"));
1292 menu.Append(PopUp_DeleteCollection, _T("&Delete collection"));
1294 if (data->IsDicomNode())
1298 std::string str("&Remove ");
1299 str += data->GetDicomNode()->GetTypeName();
1300 menu.Append(PopUp_Remove, std2wx(str));
1304 if ((data->GetDicomNode()>0)&&
1305 ( data->GetDicomNode()->GetType()<DicomNode::Image))
1307 int ctype = data->GetDicomNode()->GetType()+1;
1308 if (mSettings.HasActiveComparator(ctype))
1310 wxMenu* sortmenu = new wxMenu;
1312 Settings::ComparatorsList::iterator i;
1313 for (i =mSettings.GetComparatorsList(ctype).begin();
1314 i !=mSettings.GetComparatorsList(ctype).end();
1317 sortmenu->AppendRadioItem(PopUp_Sort+n, std2wx(i->GetName()));
1321 sortmenu->Check(PopUp_Sort+
1322 mSettings.GetActiveComparatorIndex(ctype)
1325 std::string sortmenustr("&Sort ");
1326 sortmenustr += DicomNode::GetPluralTypeName(ctype);
1327 sortmenustr += " by...";
1328 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1329 menu.AppendSubMenu(sortmenu,std2wx(sortmenustr));
1332 item->GetDicomNode()->SortChildren
1333 ( mSettings.GetActiveComparator
1334 (item->GetDicomNode()->GetType()+1)
1336 std::cout << "ok"<<std::endl;
1341 // Event : user can customize the menu
1343 ev(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU,this,id);
1347 ev.SetDicomNode(data->GetDicomNode());
1349 GetEventHandler()->ProcessEvent(ev);
1352 if (menu.GetMenuItemCount()>0) menu.AppendSeparator();
1353 menu.Append(PopUp_Settings, wxT("&Settings..."));
1354 menu.Append(PopUp_About, wxT("&About..."));
1359 wxMenu* newmenu = new wxMenu;
1360 wxMenu* openmenu = new wxMenu;
1361 Tree::RootHandlerListType::iterator h;
1363 for (h= Tree::GetRootHandlerList().begin();
1364 h!=Tree::GetRootHandlerList().end();
1367 if ((*h)->SupportsNew())
1369 newmenu->Append(PopUp_New+i, std2wx((*h)->GetName()));
1371 if ((*h)->SupportsOpen())
1372 openmenu->Append(PopUp_Open+i, std2wx((*h)->GetName()));
1376 menu.AppendSubMenu(openmenu, _T("&Open"));
1377 menu.AppendSubMenu(newmenu, _T("&New"));
1381 if ((data->IsDatabase())||(data->IsDicomNode()))
1383 Root* itroot = data->GetDicomNode()->GetDicomDatabase();
1384 // if (!itroot) itroot = data->GetDicomNode()->GetRoot();
1385 wxMenu* insertmenu = new wxMenu;
1386 bool hasone = false;
1388 Tree::RootListType::iterator j;
1389 for (j = mTree->GetDatabaseList().begin();
1390 j != mTree->GetDatabaseList().end();
1393 // std::cout << (*j)->GetName() << " "
1394 // << (*j)->GetTypeName()
1395 // << " i="<<(*j)->SupportsInsert()<<std::endl;
1396 if ( ((*j)!=itroot) && ((*j)->SupportsInsert()) )
1398 insertmenu->Append(PopUp_Insert+i,
1399 std2wx((*j)->GetName()));
1405 if (hasone) menu.AppendSubMenu(insertmenu, _T("&Insert into"));
1407 if (data->IsDatabase())
1409 menu.Append(PopUp_Close, wxT("&Close"));
1411 if (data->IsDicomNode() && data->GetDicomNode()->GetDicomDatabase()->SupportsRemove())
1413 menu.Append(PopUp_Remove, wxT("&Remove"));
1421 PopupMenu(&menu, pt);
1422 #endif // wxUSE_MENUS
1424 // std::cout << "EO ShowMenu" <<std::endl;
1426 //=====================================================================
1428 //=====================================================================
1429 // Pop up menu callbacks
1430 void WxGimmick::OnPopUpAbout(wxCommandEvent& event)
1432 wxMessageBox( _T("Give me my medical images quick ! \n\n (c) CREATIS-LRMN 2008\n"),
1434 wxOK | wxICON_INFORMATION, this);
1436 //=====================================================================
1438 //=====================================================================
1439 void WxGimmick::OnPopUpSettings(wxCommandEvent& event)
1441 WxGimmickSettingsDialog* s =
1442 new WxGimmickSettingsDialog(this);
1446 //=====================================================================
1448 //=====================================================================
1449 void WxGimmick::OnPopUpNewCollection(wxCommandEvent& event)
1452 OpenOrNewDatabase(false);
1454 //=====================================================================
1458 //=====================================================================
1459 void WxGimmick::OnPopUpOpenCollection(wxCommandEvent& event)
1462 OpenOrNewDatabase(true);
1464 //=====================================================================
1467 //=====================================================================
1468 void WxGimmick::OnPopUpCloseCollection(wxCommandEvent& event)
1470 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;
1473 // std::cout << "OnPopUpClose"<<std::endl;
1474 // wxTreeItemId id = event.GetId();
1475 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1476 DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
1477 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1478 DeleteDicomDatabase(mItemOfMenu,r);
1480 //=====================================================================
1482 //=====================================================================
1483 void WxGimmick::OnPopUpDeleteCollection(wxCommandEvent& event)
1485 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;
1490 // std::cout << "OnPopUpClose"<<std::endl;
1491 // wxTreeItemId id = event.GetId();
1492 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1493 DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase();
1495 wxRemoveFile(std2wx(r->GetFileName()));
1496 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1497 DeleteDicomDatabase(mItemOfMenu,r);
1500 //=====================================================================
1502 void DisplayUpdateSummary( DicomDatabase::UpdateSummary& summary,
1505 std::stringstream mess;
1506 mess << "Dirs\tscanned\t\t\t: " << summary.scanned_dirs << "\n";
1507 mess << "Files\tscanned\t\t\t: " << summary.scanned_files << "\n";
1508 mess << "Files\thandled\t\t\t: " << summary.handled_images << "\n\n";
1509 mess << "Patients\tadded\t\t: " << summary.added_patients<< "\n";
1510 mess << "Studies\tadded\t\t: " << summary.added_studies<< "\n";
1511 mess << "Series\tadded\t\t: " << summary.added_series<< "\n";
1512 mess << "Images\tadded\t\t: " << summary.added_images<< "\n\n";
1514 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",
1516 (int)( summary.parse_time*100./summary.total_time),
1517 summary.file_scan_time,
1518 (int)(summary.file_scan_time*100./summary.total_time),
1519 summary.update_structs_time,
1520 (int)(summary.update_structs_time*100./summary.total_time),
1521 summary.update_database_time,
1522 (int)(summary.update_database_time*100./summary.total_time),
1523 summary.total_time );
1527 wxMessageBox(std2wx(mess.str()),_T("Update summary"),wxOK,parent);
1531 //=====================================================================
1532 void WxGimmick::OnPopUpAddFile(wxCommandEvent& event)
1534 long style = wxOPEN | wxFILE_MUST_EXIST | wxFD_MULTIPLE;
1535 std::string wc("*.*");
1536 wxFileDialog* FD = new wxFileDialog( 0,
1544 if (FD->ShowModal()==wxID_OK)
1548 mCurrentDirectory = FD->GetDirectory();
1549 wxArrayString files;
1550 FD->GetPaths(files);
1552 std::vector<std::string> filenames;
1553 for (i=0;i<files.GetCount();++i)
1554 filenames.push_back(wx2std(files[i]));
1557 TreeItemData *data =
1559 mTreeListCtrl->GetItemData(mItemOfMenu);
1560 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1561 DicomDatabase::UpdateSummary summary;
1562 wxProgressDialog* progress =
1563 new wxProgressDialog(_T("Adding file(s)"),
1568 wxPD_ESTIMATED_TIME |
1569 wxPD_REMAINING_TIME |
1572 db->AddFiles(filenames,progress,summary);
1574 progress->Pulse(_T("Updating view..."));
1575 UpdateDicomDatabaseView(db);
1577 DisplayUpdateSummary(summary,this);
1581 //=====================================================================
1583 //=====================================================================
1584 void WxGimmick::OnPopUpAddRawFile(wxCommandEvent& event)
1586 wxMessageBox(_T("Not yet implemented !"),_T("Sorry"),wxOK,this);
1588 //=====================================================================
1590 //=====================================================================
1591 void WxGimmick::OnPopUpAddDirectory(wxCommandEvent& event)
1593 long style = wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST;
1596 _T("Select directory"),
1600 if (FD->ShowModal()==wxID_OK)
1603 bool recurse = false;
1604 if (wxMessageBox(_T("Recurse into sub-directories ?"),
1605 _T("Scan directory"),
1606 wxYES_NO,this ) == wxYES)
1612 wxProgressDialog* progress =
1613 new wxProgressDialog(_T("Scanning directory"),
1614 _T("Parsing directory"),
1618 wxPD_ESTIMATED_TIME |
1619 wxPD_REMAINING_TIME |
1621 DicomDatabase::UpdateSummary summary;
1623 std::string dirname = wx2std (FD->GetPath()) ;
1624 mCurrentDirectory = FD->GetPath();
1625 TreeItemData *data =
1627 mTreeListCtrl->GetItemData(mItemOfMenu);
1628 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1629 db->AddDirectory(dirname,recurse,progress,summary);
1631 progress->Pulse(_T("Updating view..."));
1632 UpdateDicomDatabaseView(db);
1635 DisplayUpdateSummary(summary,this);
1637 if (summary.cancelled_by_user)
1639 std::cout << "!! Cancelled by user !!"<<std::endl;
1645 //=====================================================================
1647 //=====================================================================
1648 void WxGimmick::OnPopUpRemove(wxCommandEvent& event)
1652 wxMessageBox(_T("Not yet implemented"),_T("Sorry !"),wxOK);
1656 // wxTreeItemId id = event.GetId();
1657 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1659 std::string mess("Remove ");
1660 mess += data->GetDicomNode()->GetTypeName();
1661 mess += " from collection ?";
1662 int answer = wxMessageBox(std2wx(mess), _T("Confirm"), wxYES_NO);
1663 if (answer == wxNO) return;
1665 if ( mTreeListCtrl->IsSelected(mItemOfMenu) )
1667 wxTreeItemId next = mTreeListCtrl->GetNextSibling(mItemOfMenu);
1670 mTreeListCtrl->SelectItem(next);
1678 DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase();
1679 db->Remove(data->GetDicomNode());
1680 // std::cout << "OnPopUpClose '"<<r->GetName()<<"'"<<std::endl;
1681 // TODO : Optimize update only parent's branch
1682 UpdateDicomDatabaseView(db);
1683 // DeleteDicomDatabase(mItemOfMenu,r);
1685 //=====================================================================
1687 //=====================================================================
1688 void WxGimmick::OnPopUpSort(wxCommandEvent& event)
1691 // std::cout << "OnPopUpSort"<<std::endl;
1692 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(mItemOfMenu);
1693 int index = event.GetId() - PopUp_Sort;
1694 DicomNode* node = data->GetDicomNode();
1695 DicomNode::Type ctype = node->GetType()+1;
1696 mSettings.SetActiveComparatorIndex(ctype,index);
1698 if (node->ChildrenLoaded())
1701 mTreeListCtrl->DeleteChildren(mItemOfMenu);
1703 /* std::cout << "Sorting using '"
1704 << mSettings.GetActiveComparator(ctype).GetName()
1707 node->SortChildren ( mSettings.GetActiveComparator(ctype) );
1708 // std::cout << "ok"<<std::endl;
1712 CreateChildrenColumnsTitles(mItemOfMenu,ctype);
1713 DicomNode::ChildrenListType::iterator i;
1714 for (i=node->GetChildrenList().begin();
1715 i!=node->GetChildrenList().end();
1718 UpdateDicomNodeView(*i,mItemOfMenu);
1722 //=====================================================================
1725 //=====================================================================
1726 void WxGimmick::OnPopUpUser(wxCommandEvent& event)
1728 // std::cout << "OnPopUpUser"<<std::endl;
1731 //=====================================================================
1733 //=================================================
1734 void WxGimmick::CreateImageList(int size)
1738 mTreeListCtrl->SetImageList(NULL);
1747 // should correspond to Icon_xxx enum
1748 icons[Icon_Patient] = wxIcon(patient_xpm);
1749 icons[Icon_Study] = wxIcon(study_xpm);
1750 icons[Icon_Series] = wxIcon(series_xpm);
1751 icons[Icon_Image] = wxIcon(image_xpm);
1752 icons[Icon_Database] = wxIcon(database_xpm);
1753 icons[Icon_Folder] = wxIcon(folder_xpm);
1754 icons[Icon_DicomDir] = wxIcon(dicomdir_xpm);
1755 icons[Icon_Root] = wxIcon(root_xpm);
1758 // mFirstRootIconIndex = 8;
1761 Tree::RootHandlerListType::iterator h;
1763 for (h= Tree::GetDatabaseHandlerList().begin();
1764 h!=Tree::GetDatabaseHandlerList().end();
1767 icons[mFirstRootIconIndex+i] = (*h)->GetIcon();
1771 unsigned int NbIcons = 8;//mFirstRootIconIndex + i;
1772 // Make an image list containing small icons
1773 wxImageList *images = new wxImageList(size, size, true);
1775 int sizeOrig = icons[0].GetWidth();
1776 for ( size_t i = 0; i < NbIcons; i++ )
1778 if ( size == sizeOrig )
1780 images->Add(icons[i]);
1784 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
1787 mTreeListCtrl->AssignImageList(images);
1789 //=================================================
1798 //================================================================
1799 bool WxGimmick::IsImageSelectable(DicomNode* node)
1801 int rows = node->ImageGetRows();
1802 int cols = node->ImageGetColumns();
1803 int frms = node->ImageGetFrames();
1805 // std::cout << "R/C/F = " << rows << "/"<< cols <<"/"<<frms<<std::endl;
1809 else if (cols>0) dim=2;
1810 else if (rows>0) dim=1;
1814 std::cout << "Unknown image dimension : cannot select !"
1818 else if (dim>mSelectionMaxImageDimension)
1820 std::cout << "Selecting "<<dim<<"D images is not allowed !"
1825 if ( mTreeListCtrl->GetSelectionSize() == 0 )
1827 mCurrentSelectionImageSize[0] = cols;
1828 mCurrentSelectionImageSize[1] = rows;
1829 mCurrentSelectionImageSize[2] = frms;
1834 if ( dim == mSelectionMaxImageDimension )
1836 std::cout << "Cannot add this image to selection : would result in a "<<dim+1<<"D image !" << std::endl;
1839 if ( ( cols != mCurrentSelectionImageSize[0] ) ||
1840 ( rows != mCurrentSelectionImageSize[1] ) ||
1841 ( frms != mCurrentSelectionImageSize[2] ) )
1843 std::cout << "Cannot add this image to selection : image size is incomptatible with currently selected images" << std::endl;
1847 // std::cout << "Selecting : "<<node->ImageGetFullFileName() << std::endl;
1850 //================================================================
1852 //================================================================
1853 void WxGimmick::OnSelChanging(wxTreeEvent& event)
1856 wxTreeItemId id = event.GetItem();
1859 std::cout << "INTERNAL ERROR : ID NOT OK"<<std::endl;
1864 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
1865 if (data->IsDicomNode())
1867 if (data->GetDicomNode()>0)
1869 // An image was selected
1870 if (data->GetDicomNode()->GetType()==DicomNode::Image)
1872 if (IsImageSelectable(data->GetDicomNode())) event.Allow();
1874 // A series was selected
1875 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
1877 // If images not loaded do it
1879 // can be selected if all its images can
1881 wxTreeItemIdValue cookie;
1882 for (child = mTreeListCtrl->GetFirstChild(id,cookie);
1884 child = mTreeListCtrl->GetNextChild(id,cookie))
1886 TreeItemData *cdata =
1887 (TreeItemData *)mTreeListCtrl->GetItemData(child);
1888 if ((cdata->IsDicomNode())&&
1889 (cdata->GetDicomNode()>0)&&
1890 (cdata->GetDicomNode()->GetType()==DicomNode::Image)&&
1891 (!IsImageSelectable(cdata->GetDicomNode())))
1899 //================================================================
1901 //================================================================
1902 void WxGimmick::OnSelChanged(wxTreeEvent& event)
1904 // wxBusyCursor busy;
1905 // std::vector<wxTreeItemId> items;
1906 // GetSelectedItems(items);
1908 std::vector<DicomNode*>::iterator i;
1909 for (i=nodes.begin();i!=nodes.end();++i)
1911 std::cout << "'" << (*i)->GetFieldValue("FullFileName")
1912 << "'" << std::endl;
1914 std::cout << "++++++++++++++++++++" << std::endl;
1916 // ShowImage(mReader.GetImage(""));
1918 bool no_image = true;
1920 static int max = 1000;
1923 // if (items.size()>0)
1926 // Update image preview : send requests to the MTImageReader
1927 // bool first = true;
1928 // std::vector<wxTreeItemId>::iterator i;
1929 // for (i=items.begin();i!=items.end();++i)
1935 DicomNode* node = GetDicomNodeOfItem(items[0]);
1937 // Update dicom fields panel
1938 mFieldsView->UpdateValues(node);
1942 wxTreeItemId item = mTreeListCtrl->GetCurrent();
1944 DicomNode* n = GetDicomNodeOfItem(item);
1946 if (n) mFieldsView->UpdateValues(n);
1949 (n->GetType()==DicomNode::Image) )
1954 //if (i==items.begin())
1955 mCurImageItemToShow = item;
1957 int maxprio = mReader.GetMaximalPriority();
1958 int prio = maxprio + 1000;
1959 wxTreeItemId sib = item; //GetTreeListCtrl()->GetNextSibling(*i);
1962 DicomNode* nsib = GetDicomNodeOfItem(sib);
1965 // std::cout << "-- Request '"
1966 // << nsib->GetFieldValue("FullFileName")
1967 // << "' prio="<<prio<<std::endl;
1968 mReader.Request(this,
1969 nsib->ImageGetFullFileName(),
1971 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
1975 sib = GetTreeListCtrl()->GetNextSibling(sib);
1977 prio = maxprio + 1000;
1978 sib = GetTreeListCtrl()->GetPrevSibling(item);
1981 DicomNode* nsib = GetDicomNodeOfItem(sib);
1984 // std::cout << "-- Request '"
1985 // << nsib->GetFieldValue("FullFileName")
1986 // << "' prio="<<prio<<std::endl;
1987 mReader.Request(this,
1988 nsib->ImageGetFullFileName(),
1990 mImageFileNameToNode[nsib->ImageGetFullFileName()] =
1994 sib = GetTreeListCtrl()->GetPrevSibling(sib);
1996 // mImageFileNameToNode[n->GetFieldValue("FullFileName")] = n;
1999 ProcessImageEvents();
2001 // std::cout << "* Selection changed * (im)"<<std::endl;
2003 //---------------------------------------------------------------------
2005 WxGimmickEvent ev(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED,
2009 GetEventHandler()->ProcessEvent(ev);
2011 if (no_image) ShowImage(mReader.GetImage(""));
2014 //================================================================
2016 //================================================================
2017 void WxGimmick::ShowImage(vtkImageData* im)
2019 // wxBusyCursor busy;
2021 int x1,x2,y1,y2,z1,z2;
2023 im->GetSpacing(spx,spy,spz);
2024 im->GetExtent (x1,x2,y1,y2,z1,z2);
2027 std::cout << x1 << "-"<<x2<<std::endl;
2028 std::cout << y1 << "-"<<y2<<std::endl;
2029 std::cout << z1 << "-"<<z2<<std::endl;
2030 std::cout << spx << "-"<<spy<<"-"<<spz<<std::endl;
2054 vtkCamera *camera = mViewer->GetRenderer()->GetActiveCamera();
2056 camera->SetViewUp ( spx*0, -spy*1, spz*0);
2057 camera->SetPosition( spx*(x1+x2)/2, spy*(y1+y2)/2, -spz*10000000);
2058 camera->SetFocalPoint ( spx*(x1+x2)/2 , spy*(y1+y2)/2 , spz*0);
2060 camera->ComputeViewPlaneNormal();
2061 camera->SetParallelScale( spx*(x2-x1)/2.0 );
2065 mViewer->SetInput( im );
2066 mViewer->SetSlice( 0 );
2067 mInteractor->Render();
2069 //================================================================
2076 //================================================================
2078 OnMultiThreadImageReaderEvent(const std::string& filename,
2079 MultiThreadImageReaderUser::EventType e,
2080 vtkImageData* image)
2082 if (filename.size()==0)
2084 mImageEventQueue.push_back(ImageEventType(image));
2087 std::map<std::string,DicomNode*>::iterator i;
2088 i = mImageFileNameToNode.find(filename);
2089 if (i!=mImageFileNameToNode.end())
2091 wxTreeItemId id = i->second->GetData<NodeData*>()->GetTreeItemData()->GetItemId();
2092 mImageEventQueue.push_back(ImageEventType(id,image));
2095 //================================================================
2097 //================================================================
2098 // Processes the queue of image events
2099 void WxGimmick::ProcessImageEvents()
2101 // std::cout << "++++++++++ ProcessImageEvents " << std::endl;
2102 MultiThreadImageReaderEventLock();
2105 while (!mImageEventQueue.empty())
2107 ImageEventType e = mImageEventQueue.front();
2108 mImageEventQueue.pop_front();
2113 mTreeListCtrl->SetItemTextColour(e.item,
2114 mSettings.LoadedImageColour());//wxImageLoadedColour);
2115 TreeItemData *data =
2116 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2117 data->SetLoaded(true);
2119 if (mCurImageItemToShow == e.item)
2124 else if (!mCurImageItemToShow.IsOk())
2129 else if (e.item.IsOk())
2131 mTreeListCtrl->SetItemTextColour(e.item,mSettings.Colour(DicomNode::Image)); //.wxImageUnloadedColour);
2132 TreeItemData *data =
2133 (TreeItemData *)mTreeListCtrl->GetItemData(e.item);
2134 data->SetLoaded(false);
2137 mImageEventQueue.clear();
2138 MultiThreadImageReaderEventUnlock();
2139 // std::cout << "++++++++++ END ProcessImageEvents " << std::endl;
2141 //================================================================
2143 //================================================================
2144 void WxGimmick::OnInternalIdle()
2146 ProcessImageEvents();
2148 //================================================================
2151 //================================================================
2152 // LG : For the moment any selection is valid but in the future
2153 // incomplete selections can be invalid...
2154 bool WxGimmick::IsSelectionValid()
2156 return (mTreeListCtrl->GetSelectionSize()>0);
2158 //================================================================
2160 //================================================================
2161 void WxGimmick::GetSelectedFiles(std::vector<std::string>& f)
2163 wxArrayTreeItemIds id;
2164 // TO DO : TEST THAT STYLE IS MULTIPLE
2165 unsigned int nb = mTreeListCtrl->GetSelections(id);
2167 for (unsigned int i=0; i<nb; ++i)
2169 TreeItemData *data =
2170 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2171 if ((data) && (data->IsDicomNode()))
2173 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2175 f.push_back ( data->GetDicomNode()->ImageGetFullFileName() );
2177 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2179 DicomNode::ChildrenListType::iterator j;
2180 for (j =data->GetDicomNode()->GetChildrenList().begin();
2181 j!=data->GetDicomNode()->GetChildrenList().end();
2184 f.push_back((*j)->ImageGetFullFileName());
2190 //================================================================
2192 //================================================================
2193 void WxGimmick::GetSelectedImages(std::vector<vtkImageData*>& f)
2195 wxArrayTreeItemIds id;
2196 // TO DO : TEST THAT STYLE IS MULTIPLE
2197 unsigned int nb = mTreeListCtrl->GetSelections(id);
2200 // Collect the brute vector of Image nodes
2201 std::vector<DicomNode*> im;
2202 for (unsigned int i=0; i<nb; ++i)
2204 TreeItemData *data =
2205 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2206 if ((data) && (data->IsDicomNode()))
2208 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2210 im.push_back ( data->GetDicomNode() );
2213 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2215 DicomNode::ChildrenListType::iterator j;
2216 for (j =data->GetDicomNode()->GetChildrenList().begin();
2217 j!=data->GetDicomNode()->GetChildrenList().end();
2220 im.push_back ( *j );
2225 // Create the output data
2228 // Only one image : give it
2229 vtkImageData* out = vtkImageData::New();
2230 out->ShallowCopy(mReader.GetImage(im.front()->ImageGetFullFileName()));
2233 else if (im.size()>1)
2235 vtkImageData* first = mReader.GetImage( im.front()->ImageGetFullFileName() );
2236 if (first->GetDataDimension()==2)
2239 vtkImageData* out = vtkImageData::New();
2240 out->CopyStructure(first);
2241 out->SetScalarType(first->GetScalarType());
2243 first->GetExtent(ext);
2245 out->SetExtent(ext);
2246 // LG : TODO : Z Spacing ?
2248 out->AllocateScalars();
2250 //first->Print(std::cout);
2251 // out->Print(std::cout);
2254 first->GetDimensions(dim);
2255 unsigned long imsize =
2256 ( (unsigned long)first->GetScalarPointer(0,1,0)
2257 - (unsigned long)first->GetScalarPointer(0,0,0))
2261 std::vector<DicomNode*>::iterator it;
2262 for (it=im.begin(); it!=im.end(); ++it)
2264 //std::cout << "copying slice "<<slice <<std::endl;
2265 vtkImageData* cur = mReader.GetImage( (*it)->ImageGetFullFileName() );
2267 void* src = cur->GetScalarPointer(0,0,0);
2268 void* dst = out->GetScalarPointer(0,0,slice);
2269 // std::cout << "src="<<src<<std::endl;
2270 // std::cout << "dst="<<dst<<std::endl;
2271 // std::cout << "siz="<<imsize<<std::endl;
2272 memcpy(dst,src,imsize);
2277 for (ii=1;ii<4;ii++) {
2278 for (jj=1;jj<4;jj++) {
2279 int x = (int)(ii*dim[0] / 4);
2280 int y = (int)(jj*dim[1] / 4);
2281 std::cout << cur->GetScalarComponentAsFloat(x,y,0,0)
2283 << out->GetScalarComponentAsFloat(x,y,slice,0)
2296 std::vector<DicomNode*>::iterator it;
2297 for (it=im.begin(); it!=im.end(); ++it)
2299 vtkImageData* out = vtkImageData::New();
2300 out->ShallowCopy(mReader.GetImage((*it)->ImageGetFullFileName()));
2306 //================================================================
2309 //================================================================
2310 void WxGimmick::GetSelectedDicomNodes(std::vector<DicomNode*>& f)
2312 wxArrayTreeItemIds id;
2313 // TO DO : TEST THAT STYLE IS MULTIPLE
2314 unsigned int nb = mTreeListCtrl->GetSelections(id);
2316 for (unsigned int i=0; i<nb; ++i)
2318 TreeItemData *data =
2319 (TreeItemData *)mTreeListCtrl->GetItemData(id[i]);
2320 if ((data) && (data->IsDicomNode()))
2322 f.push_back ( data->GetDicomNode() );
2326 if (data->GetDicomNode()->GetType()==DicomNode::Image)
2328 f.push_back ( data->GetDicomNode() ); //->ImageGetFullFileName() );
2330 else if (data->GetDicomNode()->GetType()==DicomNode::Series)
2332 DicomNode::ChildrenListType::iterator j;
2333 for (j =data->GetDicomNode()->GetChildrenList().begin();
2334 j!=data->GetDicomNode()->GetChildrenList().end();
2337 f.push_back((*j)); //->ImageGetFullFileName() ); }
2343 //================================================================
2345 //================================================================
2346 void WxGimmick::GetSelectedItems(std::vector<wxTreeItemId>& f)
2348 wxArrayTreeItemIds id;
2349 // TO DO : TEST THAT STYLE IS MULTIPLE
2350 unsigned int nb = mTreeListCtrl->GetSelections(id);
2352 for (unsigned int i=0; i<nb; ++i)
2357 //================================================================
2359 //================================================================
2360 DicomNode* WxGimmick::GetDicomNodeOfItem(const wxTreeItemId& i)
2362 TreeItemData *data =
2363 (TreeItemData *)mTreeListCtrl->GetItemData(i);
2364 if (data) return ( data->GetDicomNode() );
2367 //================================================================
2369 //================================================================
2370 //================================================================
2371 //================================================================
2372 //================================================================
2388 //================================================================
2389 //================================================================
2390 //================================================================
2391 //================================================================
2393 BEGIN_EVENT_TABLE(WxGimmick, wxPanel)
2395 EVT_MENU(PopUp_NewCollection,WxGimmick::OnPopUpNewCollection)
2396 EVT_MENU(PopUp_OpenCollection,WxGimmick::OnPopUpOpenCollection)
2397 EVT_MENU(PopUp_CloseCollection,WxGimmick::OnPopUpCloseCollection)
2398 EVT_MENU(PopUp_DeleteCollection,WxGimmick::OnPopUpDeleteCollection)
2399 EVT_MENU(PopUp_AddFile, WxGimmick::OnPopUpAddFile)
2400 EVT_MENU(PopUp_AddRawFile, WxGimmick::OnPopUpAddRawFile)
2401 EVT_MENU(PopUp_AddDirectory, WxGimmick::OnPopUpAddDirectory)
2402 EVT_MENU(PopUp_Remove, WxGimmick::OnPopUpRemove)
2403 EVT_MENU(PopUp_About, WxGimmick::OnPopUpAbout)
2404 EVT_MENU(PopUp_Settings, WxGimmick::OnPopUpSettings)
2406 EVT_MENU_RANGE(PopUp_Sort, PopUp_Sort+99, WxGimmick::OnPopUpSort)
2407 EVT_MENU_RANGE(PopUp_User, PopUp_User+99, WxGimmick::OnPopUpUser)
2412 EVT_TREE_BEGIN_DRAG(TreeListCtrlId, WxGimmick::OnBeginDrag)
2413 EVT_TREE_BEGIN_RDRAG(TreeListCtrlId, WxGimmick::OnBeginRDrag)
2414 EVT_TREE_END_DRAG(TreeListCtrlId, WxGimmick::OnEndDrag)
2417 EVT_TREE_BEGIN_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnBeginLabelEdit)
2418 EVT_TREE_END_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnEndLabelEdit)
2421 EVT_TREE_DELETE_ITEM(TreeListCtrlId, WxGimmick::OnDeleteItem)
2422 #if 0 // there are so many of those that logging them causes flicker
2423 EVT_TREE_GET_INFO(TreeListCtrlId, WxGimmick::OnGetInfo)
2426 EVT_TREE_SET_INFO(TreeListCtrlId, WxGimmick::OnSetInfo)
2429 EVT_TREE_ITEM_EXPANDED(TreeListCtrlId, WxGimmick::OnItemExpanded)
2430 EVT_TREE_ITEM_EXPANDING(TreeListCtrlId, WxGimmick::OnItemExpanding)
2431 EVT_TREE_ITEM_COLLAPSED(TreeListCtrlId, WxGimmick::OnItemCollapsed)
2432 EVT_TREE_ITEM_COLLAPSING(TreeListCtrlId, WxGimmick::OnItemCollapsing)
2435 EVT_TREE_SEL_CHANGED(TreeListCtrlId, WxGimmick::OnSelChanged)
2436 EVT_TREE_SEL_CHANGING(TreeListCtrlId, WxGimmick::OnSelChanging)
2438 EVT_TREE_KEY_DOWN(TreeListCtrlId, WxGimmick::OnTreeKeyDown)
2439 // ACTIVATION = DOUBLE CLICK OR ENTER ON SELECTED
2440 EVT_TREE_ITEM_ACTIVATED(TreeListCtrlId, WxGimmick::OnItemActivated)
2442 // so many differents ways to handle right mouse button clicks...
2443 // EVT_CONTEXT_MENU(WxGimmick::OnContextMenu)
2444 // EVT_TREE_ITEM_MENU is the preferred event for creating context menus
2445 // on a tree control, because it includes the point of the click or item,
2446 // meaning that no additional placement calculations are required.
2447 // EVT_TREE_ITEM_MENU(TreeListCtrlId, WxGimmick::OnItemMenu)
2449 EVT_TREE_ITEM_RIGHT_CLICK(TreeListCtrlId, WxGimmick::OnItemRightClick)
2452 // EVT_RIGHT_DOWN(WxGimmick::OnRMouseDown)
2453 // EVT_RIGHT_UP(WxGimmick::OnRMouseUp)
2454 // EVT_RIGHT_DCLICK(WxGimmick::OnRMouseDClick)
2457 //IMPLEMENT_DYNAMIC_CLASS(WxGimmick, wxTreeListCtrl)
2460 wxTree::wxTree(wxWindow *parent, const wxWindowID id,
2461 const wxPoint& pos, const wxSize& size,
2463 : wxTreeListCtrl(parent, id, pos, size, style)
2465 m_reverseSort = false;
2469 // Add some items to the tree
2470 AddTestItemsToTree(5, 2);
2476 #if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
2477 void WxGimmick::CreateButtonsImageList(int size)
2482 mTreeListCtrl->SetButtonsImageList(NULL);
2486 // Make an image list containing small icons
2487 wxImageList *images = new wxImageList(size, size, true);
2489 // should correspond to TreeListCtrlIcon_xxx enum
2492 icons[0] = wxIcon(icon3_xpm); // closed
2493 icons[1] = wxIcon(icon3_xpm); // closed, selected
2494 icons[2] = wxIcon(icon5_xpm); // open
2495 icons[3] = wxIcon(icon5_xpm); // open, selected
2497 for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
2499 int sizeOrig = icons[i].GetWidth();
2500 if ( size == sizeOrig )
2502 images->Add(icons[i]);
2506 images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
2510 mTreeListCtrl->AssignButtonsImageList(images);
2513 void WxGimmick::CreateButtonsImageList(int WXUNUSED(size))
2519 int WxGimmick::OnCompareItems(const wxTreeItemId& item1,
2520 const wxTreeItemId& item2)
2522 if ( m_reverseSort )
2524 // just exchange 1st and 2nd items
2525 return mTreeListCtrl->OnCompareItems(item2, item1);
2529 return mTreeListCtrl->OnCompareItems(item1, item2);
2534 void WxGimmick::DoToggleIcon(const wxTreeItemId& item)
2537 int image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_Folder)
2540 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Normal);
2542 image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_FolderSelected)
2543 ? TreeIcon_FileSelected
2544 : TreeIcon_FolderSelected;
2545 mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Selected);
2548 void WxGimmick::LogEvent(const wxChar *name, const wxTreeEvent& event)
2550 wxTreeItemId item = event.GetItem();
2553 text << _T('"') << mTreeListCtrl->GetItemText(item).c_str() << _T('"');
2555 text = _T("invalid item");
2556 // wxLogMessage(wxT("%s(%s)"), name, text.c_str());
2561 #define TREE_EVENT_HANDLER(name) \
2562 void WxGimmick::name(wxTreeEvent& event) \
2564 /* LogEvent(_T(#name), event); */ \
2565 /* SetLastItem(mTreeListCtrl->wxTreeItemId()) *;*/ \
2569 TREE_EVENT_HANDLER(OnBeginRDrag)
2570 TREE_EVENT_HANDLER(OnDeleteItem)
2571 TREE_EVENT_HANDLER(OnGetInfo)
2572 TREE_EVENT_HANDLER(OnSetInfo)
2573 //TREE_EVENT_HANDLER(OnItemExpanded)
2574 TREE_EVENT_HANDLER(OnItemExpanding)
2575 //TREE_EVENT_HANDLER(OnItemCollapsed)
2576 //TREE_EVENT_HANDLER(OnSelChanged)
2577 // TREE_EVENT_HANDLER(OnSelChanging)
2580 void WxGimmick::OnItemCollapsed(wxTreeEvent& event)
2582 // std::cout << "* Collapsed *"<<std::endl;
2585 #undef TREE_EVENT_HANDLER
2587 void WxGimmick::OnTreeKeyDown(wxTreeEvent& event)
2590 // LogKeyEvent(wxT("Tree key down "), event.GetKeyEvent());
2591 std::cout << "* Key down *"<<std::endl;
2592 if (event.GetKeyCode()==WXK_RIGHT)
2594 std::cout << "Right"<<std::endl;
2595 wxTreeItemId itemId = mTreeListCtrl->GetSelection();
2598 std::cout << "item is ok"<<std::endl;
2599 wxPoint clientpt = event.GetPoint();
2600 wxPoint screenpt = ClientToScreen(clientpt);
2601 ShowMenu(itemId, clientpt);
2606 std::cout << "NOT Right"<<std::endl;
2611 void WxGimmick::OnBeginDrag(wxTreeEvent& event)
2613 wxTreeItemId id = event.GetItem();
2614 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2615 // std::cout << "OnBeginDrag("<<id<<")"<<std::endl;
2616 if (data->IsDatabase())
2618 // std::cout << "-- IS ROOT"<<std::endl;
2621 else if (data->IsDicomNode())
2623 // std::cout << "-- IS NODE"<<std::endl;
2626 // need to explicitly allow drag
2627 if ( event.GetItem() != GetDatabaseItem() )
2629 m_draggedItem = event.GetItem();
2631 wxPoint clientpt = event.GetPoint();
2632 wxPoint screenpt = ClientToScreen(clientpt);
2634 wxLogMessage(wxT("OnBeginDrag: started dragging %s at screen coords (%i,%i)"),
2635 GetItemText(m_draggedItem).c_str(),
2636 screenpt.x, screenpt.y);
2642 wxLogMessage(wxT("OnBeginDrag: this item can't be dragged."));
2647 void WxGimmick::OnEndDrag(wxTreeEvent& event)
2649 wxTreeItemId id = event.GetItem();
2650 // std::cout << "OnEndDrag("<<id<<")"<<std::endl;
2651 if (!id.IsOk()) return;
2652 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2653 if (data->IsDatabase())
2655 // std::cout << "-- IS ROOT"<<std::endl;
2657 else if (data->IsDicomNode())
2659 // std::cout << "-- IS NODE"<<std::endl;
2663 wxTreeItemId itemSrc = m_draggedItem,
2664 itemDst = event.GetItem();
2665 m_draggedItem = (wxTreeItemId)0l;
2667 // where to copy the item?
2668 if ( itemDst.IsOk() && !ItemHasChildren(itemDst) )
2670 // copy to the parent then
2671 itemDst = GetItemParent(itemDst);
2674 if ( !itemDst.IsOk() )
2676 wxLogMessage(wxT("OnEndDrag: can't drop here."));
2681 wxString text = GetItemText(itemSrc);
2682 wxLogMessage(wxT("OnEndDrag: '%s' copied to '%s'."),
2683 text.c_str(), GetItemText(itemDst).c_str());
2685 // just do append here - we could also insert it just before/after the item
2686 // on which it was dropped, but this requires slightly more work... we also
2687 // completely ignore the client data and icon of the old item but could
2688 // copy them as well.
2690 // Finally, we only copy one item here but we might copy the entire tree if
2691 // we were dragging a folder.
2692 int image = wxGetApp().ShowImages() ? TreeIcon_File : -1;
2693 AppendItem(itemDst, text, image);
2698 //====================================================================
2699 void WxGimmick::OnBeginLabelEdit(wxTreeEvent& event)
2701 // std::cout << "OnBeginLabelEdit"<<std::endl;
2702 wxTreeItemId id = event.GetItem();
2703 TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
2704 // If not a root : veto
2705 if (data->IsDatabase())
2712 //====================================================================
2714 //====================================================================
2715 void WxGimmick::OnEndLabelEdit(wxTreeEvent& event)
2717 // std::cout << "OnEndLabelEdit"<<std::endl;
2718 wxTreeItemId id = event.GetItem();
2719 TreeItemData *data = GetItemData(id);
2720 // If not a database : bug !
2721 if (data->IsDatabase())
2723 data->GetDicomNode()->GetDicomDatabase()->SetName(wx2std(event.GetLabel()));
2724 mFieldsView->UpdateValues(data->GetDicomNode());
2728 std::cerr<< "!!!! Internal error : send bug report !!!!"<<std::endl;
2731 //====================================================================
2734 void WxGimmick::OnItemCollapsing(wxTreeEvent& event)
2736 // wxLogMessage(wxT("OnItemCollapsing"));
2738 // for testing, prevent the user from collapsing the first child folder
2739 wxTreeItemId itemId = event.GetItem();
2742 if ( IsTestItem(itemId) )
2744 wxMessageBox(wxT("You can't collapse this item."));
2761 //================================================================
2762 //================================================================
2763 //================================================================
2764 //================================================================
2765 //================================================================
2767 //================================================================
2768 //================================================================
2769 //================================================================
2770 //================================================================
2771 //================================================================
2777 // ----------------------------------------------------------------------------
2779 // ----------------------------------------------------------------------------
2781 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_DRAG)
2782 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_RDRAG)
2783 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_DELETE_ITEM)
2784 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_GET_INFO)
2785 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SET_INFO)
2786 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDED)
2787 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDING)
2788 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSED)
2789 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSING)
2792 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT)
2793 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_LABEL_EDIT)
2796 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED)
2797 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGING)
2798 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_KEY_DOWN)
2799 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU)
2800 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_ITEM_STYLE_CHANGED)
2802 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_ACTIVATED)
2803 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK)
2804 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK)
2805 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_DRAG)
2806 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK)
2807 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP)
2808 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MENU)
2810 // ----------------------------------------------------------------------------
2812 // ----------------------------------------------------------------------------
2814 IMPLEMENT_ABSTRACT_CLASS(WxGimmickEvent, wxNotifyEvent)
2817 WxGimmickEvent::WxGimmickEvent(wxEventType commandType,
2819 const wxTreeItemId& item)
2821 wxNotifyEvent(commandType, tree->GetId()),
2825 // m_editCancelled = false;
2827 SetEventObject(tree);
2830 SetClientObject(tree->mTreeListCtrl->GetItemData(item));
2833 WxGimmickEvent::WxGimmickEvent(wxEventType commandType, int id)
2835 wxNotifyEvent(commandType, id),
2839 // m_editCancelled = false;
2842 WxGimmickEvent::WxGimmickEvent(const WxGimmickEvent & event)
2844 wxNotifyEvent(event),
2848 m_evtKey = event.m_evtKey;
2849 m_item = event.m_item;
2850 m_itemOld = event.m_itemOld;
2851 mColor = event.mColor;
2852 mUserData = event.mUserData;
2853 // m_pointDrag = event.m_pointDrag;
2854 // m_label = event.m_label;
2855 // m_editCancelled = event.m_editCancelled;
2865 //================================================================
2866 //================================================================
2867 //================================================================
2868 //================================================================
2869 //================================================================
2870 WxGimmickFrame::WxGimmickFrame( wxWindow *parent,
2873 : wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size)
2875 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
2876 mWxGimmick = new WxGimmick(this,-1,
2879 sizer->Add(mWxGimmick,1,wxGROW);
2881 SetAutoLayout(true);
2884 //================================================================
2886 //================================================================
2887 WxGimmickFrame::~WxGimmickFrame()
2890 //================================================================
2892 //================================================================
2893 void WxGimmickFrame::OnSelChanged(WxGimmickEvent& event)
2895 // std::cout << "+++++ WxGimmickFrame::OnSelChanged ++++++++++"
2897 std::vector<std::string> file;
2898 // mWxGimmick->GetSelectedImages(file);
2900 std::vector<std::string>::iterator i;
2901 for (i=file.begin();i!=file.end();++i)
2903 std::cout << "'" << *i << "'" << std::endl;
2905 std::cout << "++++++++++++++++++++" << std::endl;
2908 //================================================================
2910 //================================================================
2911 BEGIN_EVENT_TABLE(WxGimmickFrame, wxFrame)
2912 EVT_TREEVIEWLIST_SEL_CHANGED(-1,WxGimmickFrame::OnSelChanged)
2914 //================================================================
2937 //================================================================
2938 //================================================================
2939 //================================================================
2940 //================================================================
2942 //================================================================
2943 WxGimmickSettingsDialog::WxGimmickSettingsDialog(wxWindow *parent)
2959 //================================================================
2961 //================================================================
2962 WxGimmickSettingsDialog::~WxGimmickSettingsDialog()
2965 //================================================================