#include #include #include #include "icons/database.xpm" #include "icons/folder.xpm" #include "icons/dicomdir.xpm" #include "icons/patient.xpm" #include "icons/study.xpm" #include "icons/series.xpm" #include "icons/image.xpm" #include "icons/root.xpm" #include #include #include #include #include #include //#include using namespace crea; #include #include namespace creaImageIO { //================================================================ const int WxGimmick::UserMenuFirstId = 1000; //================================================================ //================================================================ typedef enum { Icon_Root, Icon_Database, Icon_Folder, Icon_DicomDir, Icon_Patient, Icon_Study, Icon_Series, Icon_Image } icon_id; //================================================================ //================================================================ enum { PopUp_NewCollection = 100, PopUp_OpenCollection = 101, PopUp_CloseCollection = 102, PopUp_DeleteCollection = 103, PopUp_AddDirectory = 110, PopUp_AddFile = 111, PopUp_AddRawFile = 112, PopUp_Remove = 120, PopUp_Sort = 200, PopUp_Settings = 501, PopUp_About = 502, PopUp_User = WxGimmick::UserMenuFirstId, }; //================================================================ //================================================================ #define TreeListCtrlId 10000 //================================================================ //================================================================ const icon_id Icon[5] = { Icon_Database, Icon_Patient, Icon_Study, Icon_Series, Icon_Image }; //================================================================ //================================================================ class WxGimmickDicomNodeData : public DicomNodeData { public: WxGimmickDicomNodeData (WxGimmickTreeItemData* d = 0) : mTreeItemData(d), mLoaded(false) {} ~WxGimmickDicomNodeData(); WxGimmickTreeItemData* GetTreeItemData() { return mTreeItemData; } void SetTreeItemData( WxGimmickTreeItemData* d) { mTreeItemData = d; } inline bool IsLoaded() { return mLoaded; } inline void SetLoaded(bool v) { mLoaded = v; } private: WxGimmickTreeItemData* mTreeItemData; bool mLoaded; }; //================================================================ //================================================================ class WxGimmickTreeItemData : public wxTreeItemData { public: WxGimmickTreeItemData(DicomNode* node) : mType(0), mDicomNode(node), // mLoaded(false), mUpdateTime(0), mUserFlags(0) { if (node) { WxGimmickDicomNodeData* data = node->GetData(); if (data!=0) { if (data->GetTreeItemData()!=0) { std::cout << "WxGimmickTreeItemData ERROR ****" << std::endl; return; } data->SetTreeItemData(this); return; } node->SetData( new WxGimmickDicomNodeData(this) ); if (node->GetType()==DicomNode::Database) { mType = 2; } else { mType = 1; } } } ~WxGimmickTreeItemData() { if (mDicomNode) { WxGimmickDicomNodeData* data = mDicomNode->GetData(); if (data) data->SetTreeItemData(0); } } inline void ResetDicomNode() { mDicomNode = 0; } inline void SetItemId ( const wxTreeItemId& item ) { mItemId = item; } inline const wxTreeItemId& GetItemId() const { return mItemId; } inline bool IsDefault() const { return (mType == 0); } inline bool IsDatabase() const { return (mType == 2); } inline bool IsDicomNode() const { return (mType == 1); } inline DicomNode* GetDicomNode() { return mDicomNode; } inline long& UpdateTime() { return mUpdateTime; } inline bool IsLoaded() { mDicomNode->GetData()->IsLoaded(); } inline void SetLoaded(bool v) { mDicomNode->GetData()->SetLoaded(v); } inline int GetUserFlags() const { return mUserFlags; } inline void SetUserFlags(int f) { mUserFlags = f; } private: // The type of item : // 0 = Default // 1 = DicomNode // 2 = DicomNode of type Database int mType; wxTreeItemId mItemId; DicomNode* mDicomNode; // bool mLoaded; long mUpdateTime; int mUserFlags; }; //================================================================ //================================================================ WxGimmickDicomNodeData::~WxGimmickDicomNodeData() { if (mTreeItemData) { mTreeItemData->ResetDicomNode(); } } //================================================================ //================================================================ //================================================================ //================================================================ //================================================================ //================================================================ //================================================================ //================================================================ WxGimmick::WxGimmick(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, int image_type, int threads) : wxPanel(parent,id,pos,size), mSelectionType(image_type), mSaveConfigurationOnClose(true), mReader(threads) { // Initialize image size corresponding to current selection switch (mSelectionType) { case GIMMICK_2D_IMAGE_SELECTION : mSelectionMaxImageDimension = 2; break; case GIMMICK_3D_IMAGE_SELECTION : mSelectionMaxImageDimension = 3; break; case GIMMICK_4D_IMAGE_SELECTION : mSelectionMaxImageDimension = 4; break; default : mSelectionMaxImageDimension = 0; } // Start the threads ... mReader.Start(); // SetDatabaseExtension("sqlite3"); // Create the UserSettings dir if does not exist CreateUserSettingsDirectory(); // Sets the current directory to the Setting dir mCurrentDirectory = std2wx(GetUserSettingsDirectory()); // Window layout creation wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL); // Left/Right split mSplitter1 = new wxSplitterWindow( this, -1); // TreeCtrl on the left long style = wxTR_HIDE_ROOT | wxTR_HAS_BUTTONS | wxTR_NO_LINES //| wxTR_LINES_AT_ROOT | wxTR_FULL_ROW_HIGHLIGHT // | wxTR_SINGLE | wxTR_MULTIPLE | wxTR_EDIT_LABELS ; /* style = style | wxTR_EDIT_LABELS //Use this style if you wish the user to be able to edit labels in the tree list control. //wxTR_NO_BUTTONS For convenience to document that no buttons are to be drawn. | wxTR_HAS_BUTTONS //Use this style to show + and - buttons to the left of parent items. | 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. //wxTR_NO_LINES Use this style to hide vertical level connectors. | 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.) | 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. | 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. // wxTR_ROW_LINES // Use this style to draw a contrasting border between displayed rows. // 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. // 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. | 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. | wxTR_EXTENDED // Use this style to allow disjoint items to be selected. (Only partially implemented; may not work in all cases.) //wxTR_DEFAULT_STYLE The set of flags that are closest to the defaults for the native control for a particular toolkit. //| wxTR_VIRTUAL //The application provides items text on demand. */ mTreeListCtrl = new wxTreeListCtrl(mSplitter1, TreeListCtrlId, wxDefaultPosition, wxDefaultSize, style); mTreeListCtrl->SetIndent(0); mTreeListCtrl->SetLineSpacing(5); CreateImageList(); // Right panel wxPanel *rpanel = new wxPanel( mSplitter1, -1 ); // Right sizer wxBoxSizer *rsizer = new wxBoxSizer(wxHORIZONTAL); // Right panel top/bottom split mSplitter2 = new wxSplitterWindow( rpanel , -1); // Image panel (top) mPanelImage = new wxPanel(mSplitter2,-1); mPanelImage->SetBackgroundColour( wxColour(0,0,0) ); // Image sizer wxBoxSizer *isizer = new wxBoxSizer(wxHORIZONTAL ); mPanelImage->SetSizer( isizer ); // Notebook mwxNotebook = new wxNotebook(mSplitter2, -1,wxDefaultPosition, wxDefaultSize, 0); // Fields view (bottom) mFieldsView = new WxGimmickFieldsView(mwxNotebook,-1, wxDefaultPosition, wxDefaultSize,0); mFieldsView->SetColors ( GetSettings().Colour(DicomNode::Database), GetSettings().BgColour(DicomNode::Database), GetSettings().Colour(DicomNode::Patient), GetSettings().BgColour(DicomNode::Patient), GetSettings().Colour(DicomNode::Study), GetSettings().BgColour(DicomNode::Study), GetSettings().Colour(DicomNode::Series), GetSettings().BgColour(DicomNode::Series), GetSettings().Colour(DicomNode::Image), GetSettings().BgColour(DicomNode::Image)); mwxNotebook->AddPage( mFieldsView, _T("Dicom fields")); // Help mHelp = new WxGimmickHelp(mwxNotebook); mwxNotebook->AddPage( mHelp, _T("Help")); // Splitting int wsize = size.GetWidth(); int hsize = size.GetHeight(); int previewhsize = 150; int previewwsize = 400; mSplitter2->SetMinimumPaneSize( previewhsize ); mSplitter2->SplitHorizontally( mPanelImage, mwxNotebook, //mFieldsView, hsize - previewhsize); rsizer->Add( mSplitter2,1,wxGROW ,0); rpanel->SetAutoLayout(true); rpanel->SetSizer( rsizer ); rpanel->Layout(); // previewer mInteractor = new crea::creawxVTKRenderWindowInteractor(mPanelImage,-1); mInteractor->UseCaptureMouseOn(); mViewer = vtkImageViewer2::New(); mViewer->SetupInteractor ( mInteractor ); mViewer->SetInput(mReader.GetImage("")); isizer-> Add( mInteractor ,1,wxGROW ,0); topsizer->Add( mSplitter1,1,wxGROW ,0); // Left/right split mSplitter1->SetMinimumPaneSize( 200 ); mSplitter1->SplitVertically(mTreeListCtrl, rpanel, wsize - previewwsize ); // ProcessImageEvents(); SetSizer( topsizer ); SetAutoLayout(true); mDatabaseListFile = GetUserSettingsDirectory(); mDatabaseListFile += "collections.txt"; LoadConfiguration(); Layout(); ShowImage(mReader.GetImage("")); // Show help if no collection if (GetDicomDatabaseList().size()==0) { mwxNotebook->SetSelection(1); } else { mwxNotebook->SetSelection(0); } // mJustStarted = true; } //================================================================ // file separator #if defined(_WIN32) #define VALID_FILE_SEPARATOR "\\" #define INVALID_FILE_SEPARATOR "/" #else #define INVALID_FILE_SEPARATOR "\\" #define VALID_FILE_SEPARATOR "/" #endif //================================================================ const std::string& WxGimmick::GetUserSettingsDirectory() { if (mUserSettingsDirectory.size()==0) { #if defined(__GNUC__) mUserSettingsDirectory = getenv("HOME"); #elif defined(_WIN32) mUserSettingsDirectory = getenv("USERPROFILE"); #endif mUserSettingsDirectory += "/.gimmick/"; boost::algorithm::replace_all( mUserSettingsDirectory, INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR); } return mUserSettingsDirectory; } //================================================================ //======================================================================== void WxGimmick::CreateUserSettingsDirectory() { if (! boost::filesystem::is_directory( GetUserSettingsDirectory() ) ) { creaMessage("Gimmick!",1,"==> Directory '"<Delete(); delete mInteractor; } //================================================================ //================================================================ void WxGimmick::RebuildView() { wxBusyCursor busy; mTreeListCtrl->DeleteRoot(); //DeleteAllItems(); // mTreeDefaultItemId = wxTreeItemId(); int nbattr = mSettings.GetMaxNumberOfColumns(); for (int j=0;jAddColumn (_T(""), 200, //DEFAULT_COL_WIDTH, wxALIGN_LEFT, -1, true, false); } mTreeListCtrl->SetMainColumn (0); mTreeListCtrl->SetColumnEditable (0, true); mTreeRootId = mTreeListCtrl->AddRoot( _T(""),Icon_Root,Icon_Root); // The collections columns legends mCollectionsTitlesItemId = CreateChildrenColumnsTitles(mTreeRootId,DicomNode::Database); DicomDatabaseListType::iterator i; for (i =GetDicomDatabaseList().begin(); i!=GetDicomDatabaseList().end(); ++i) { UpdateDicomDatabaseView(*i); } mTreeListCtrl->Expand(mTreeRootId); // LG : test // mTreeListCtrl->ExpandAll(mTreeRootId); // std::cout << "EO RebuildAll"<GetFirstChild(mTreeRootId,cookie); dbid.IsOk(); dbid = mTreeListCtrl->GetNextChild(mTreeRootId,cookie)) { data = (TreeItemData *)mTreeListCtrl->GetItemData(dbid); if ((data->IsDatabase())&&(data->GetDicomNode()==db)) break; } // Not found : create if (!dbid.IsOk()) { // Icon int iconid = Icon[DicomNode::Database]; // Creation // std::cout << " -> Creating item for '"<GetLabel()<<"'"<AppendItem( mTreeRootId, std2wx(db->GetLabel()), iconid, iconid, data ); data->SetItemId(dbid); mTreeListCtrl->SetItemTextColour (dbid,mSettings.Colour(DicomNode::Database)); mTreeListCtrl->SetItemBackgroundColour (dbid,mSettings.BgColour(DicomNode::Database)); UpdateColumns(dbid); // The patients columns legends CreateChildrenColumnsTitles(dbid,DicomNode::Patient); } // Increase UpdateTime to detect obsolete items after // tree traversal data->UpdateTime()++; // Recurse DicomNode::ChildrenListType::iterator j; for (j= db->GetChildrenList().begin(); j!=db->GetChildrenList().end(); j++) { UpdateDicomNodeView(*j,dbid); } DeleteObsoleteChildren(dbid); mTreeListCtrl->EnsureVisible(dbid); } //================================================================ //================================================================ void WxGimmick::UpdateDicomNodeView(DicomNode* n, const wxTreeItemId& parent) { wxBusyCursor busy; // std::cout << "* UpdateDicomNodeView("<GetLabel()<<")"<GetType() != DicomNode::Study)) { // Does the item exist ? wxTreeItemIdValue cookie; for (newparent = mTreeListCtrl->GetFirstChild(parent,cookie); newparent.IsOk(); newparent = mTreeListCtrl->GetNextChild(parent,cookie)) { data = (TreeItemData *)mTreeListCtrl->GetItemData(newparent); if (data->GetDicomNode() == n) break; } // Not found : create if (!newparent.IsOk()) { int image(Icon[n->GetType()]); wxColour *colour(&mSettings.Colour(n->GetType())); wxColour *bgcolour(&mSettings.BgColour(n->GetType())); if (n->GetType()==DicomNode::Image) { // std::cout << "!!!Image"<GetData()!=0) { // std::cout << ">> n->GetData()!=0" << std::endl; if (n->GetData()->IsLoaded()) { colour = &mSettings.LoadedImageColour(); } // std::cout << "<< n->GetData()!=0" << std::endl; } } data = new TreeItemData(n); newparent = mTreeListCtrl->AppendItem(parent, _T(""), image, image, data); data->SetItemId(newparent); mTreeListCtrl->SetItemTextColour(newparent,*colour); mTreeListCtrl->SetItemBackgroundColour(newparent,*bgcolour); UpdateColumns(newparent); if (n->GetType()!=DicomNode::Image) { CreateChildrenColumnsTitles(newparent,n->GetType()+1); } } else { UpdateColumns(newparent,true); } // synchonise update time with parent TreeItemData * parent_data = (TreeItemData *)mTreeListCtrl->GetItemData(parent); data->UpdateTime() = parent_data->UpdateTime(); } DicomNode::ChildrenListType::iterator i; for (i=n->GetChildrenList().begin(); i!=n->GetChildrenList().end(); i++) { UpdateDicomNodeView(*i,newparent); } if (n->GetType() != DicomNode::Image) DeleteObsoleteChildren(newparent); } //================================================================ //================================================================ void WxGimmick::UpdateColumns(wxTreeItemId& item, bool only_first) { TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(item); DicomNode* node = data->GetDicomNode(); if (only_first) { // Update only the first field (for #children update) DicomNode* node2 = node; // If Study and Series level are merged and node type is Series // then have to get back to the Study level if ((mSettings.MergeStudySeries())&& (node->GetType() == DicomNode::Series)) node2 = node->GetParent(); std::string lab; lab += node2->GetFieldValueMap() [ mSettings.GetColumnList(node2->GetType())[0].Key ]; if (node->GetType() != DicomNode::Image) { if (node->GetChildrenList().size()>0) { char sz[100]; sprintf(sz," [%d]",node->GetNumberOfChildren()); lab += sz; } } mTreeListCtrl->SetItemText(item,std2wx(lab)); } else { int c = 0; Settings::ColumnListType::iterator col; // If Study and Series level are merged and node type is Series // then have to fill the Study level cols first if ((mSettings.MergeStudySeries())&& (node->GetType() == DicomNode::Series)) { DicomNode* node2 = node->GetParent(); for (col = mSettings.GetColumnList(node2->GetType()).begin(); col != mSettings.GetColumnList(node2->GetType()).end(); ++col) { std::string s = node2->GetFieldValueMap()[col->Key]; if (c==0) { char sz[100]; sprintf(sz," [%d]",node->GetNumberOfChildren()); s += sz; } mTreeListCtrl->SetItemText (item, c, std2wx(s)); c++; } } for (col = mSettings.GetColumnList(node->GetType()).begin(); col != mSettings.GetColumnList(node->GetType()).end(); ++col) { std::string s = node->GetFieldValueMap()[col->Key]; if ((c==0)&&(node->GetType() != DicomNode::Image)) { char sz[100]; sprintf(sz," [%d]",node->GetNumberOfChildren()); s += sz; } mTreeListCtrl->SetItemText (item, c, std2wx(s)); c++; } } } //================================================================ //================================================================ wxTreeItemId WxGimmick::CreateChildrenColumnsTitles (wxTreeItemId& item, DicomNode::Type t) { // Creates the sub-level columns titles TreeItemData* data = new TreeItemData(0); wxTreeItemId id = mTreeListCtrl->AppendItem( item, _T(""), -1, -1, data ); data->SetItemId(id); mTreeListCtrl->SetItemFont(id, *wxITALIC_FONT); mTreeListCtrl->SetItemTextColour(id, mSettings.Colour(t)); mTreeListCtrl->SetItemBackgroundColour(id, mSettings.BgColour(t)); UpdateColumnsTitles(id,t); return id; } //================================================================ //================================================================ void WxGimmick::UpdateColumnsTitles(wxTreeItemId& item, DicomNode::Type t) { // std::cout << "Update columns titles "<Name << std::endl; mTreeListCtrl->SetItemText (item, c, std2wx(col->Name)); c++; } } //================================================================ //================================================================ void WxGimmick::DeleteObsoleteChildren(wxTreeItemId& id) { TreeItemData * parent_data = (TreeItemData *)mTreeListCtrl->GetItemData(id); wxTreeItemId child; wxTreeItemIdValue cookie; std::vector children; for (child = mTreeListCtrl->GetFirstChild(id,cookie); child.IsOk(); child = mTreeListCtrl->GetNextChild(id,cookie)) { children.push_back(child); } std::vector::iterator i; for (i=children.begin();i!=children.end();++i) { TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(*i); if ( ((data->GetDicomNode()>0) && ((data->UpdateTime() != parent_data->UpdateTime()))) || ((data->IsDicomNode()) && (data->GetDicomNode()==0)) ) { // std::cout << "DOBSC="<GetItemText(*i)<Delete(*i); } } } //================================================================ //================================================================ void WxGimmick::OpenOrNewDatabase(bool open) { wxBusyCursor busy; long style = wxFD_SAVE | wxFD_OVERWRITE_PROMPT; if (open) style = wxOPEN | wxFILE_MUST_EXIST; std::string wc("*."); wc += GetDatabaseExtension(); // TO DO : Handler give their wildcards wxFileDialog* FD = new wxFileDialog( 0, _T("Select file"), mCurrentDirectory, _T(""), std2wx(wc), style, wxDefaultPosition); if (FD->ShowModal()!=wxID_OK) return; std::string filename = wx2std (FD->GetPath()); mCurrentDirectory = FD->GetDirectory(); if (!open) { boost::filesystem::path filepath(filename); boost::filesystem::change_extension(filepath,GetDatabaseExtension()); if ( boost::filesystem::exists(filepath) ) { boost::filesystem::remove(filepath); /* LG : works on Linux but not Windows : if ( ! boost::filesystem::remove(filepath) ) { wxMessageBox(_T("Could not overwrite ") +std2wx(filepath.string()), _T("Error"), wxOK,this); return; } */ } } DicomDatabase* db = new DicomDatabase(filename); bool r; if (open) { r = db->Open(); if (!r) { wxMessageBox(_T("An error occured while opening ") +std2wx(filename), _T("Error"), wxOK,this); return; } } else { wxString collname = wxGetTextFromUser(_T("Enter collection name"),_T("New collection"), _T(""),this); db->SetName(wx2std(collname)); r = db->New(); if (!r) { wxMessageBox(_T("An error occured while creating ") +std2wx(filename), _T("Error"), wxOK,this); return; } } if (GetDicomDatabaseList().size()==0) mFieldsView->UpdateFields(db); GetDicomDatabaseList().push_back(db); UpdateDicomDatabaseView(db); } //================================================================ //================================================================ void WxGimmick::LoadConfiguration() { wxBusyCursor busy; // std::cout << "WxGimmick : Reading config"< Loading collections from '"< tokens; boost::split( tokens, str, boost::is_any_of("\t") ); DicomDatabase* db = new DicomDatabase(tokens[0]); // std::cout << " -> Loading collection '"<SetName(tokens[1]); } if (db->Open()) { GetDicomDatabaseList().push_back(db); db->DBLoadChildren(db,DicomNode::Patient); if (mSettings.HasActiveComparator(DicomNode::Patient)) { db->SortChildren ( mSettings.GetActiveComparator(DicomNode::Patient) ); } } else { creaMessage("Gimmick!",1," ==> ERROR opening collection '"< File does not exist. It will be created on exit (if you already ran Gimmick! and exited normally, this is not normal. Send a bug report)."); } mTreeListCtrl->SetBackgroundColour(mSettings.BgColour(DicomNode::Database)); if (GetDicomDatabaseList().begin() != GetDicomDatabaseList().end() ) { mFieldsView->UpdateFields(*GetDicomDatabaseList().begin()); } RebuildView(); } //================================================================ //================================================================ void WxGimmick::SaveConfiguration() { wxBusyCursor busy; creaMessage("Gimmick!",1,"Gimmick! : Saving configuration..."< Saving collections in '" <GetFileName() << "\t"; s << (*i)->GetName() << std::endl; } s.close(); } //================================================================ /* //================================================================ void WxGimmick::OnClose(wxCloseEvent& event) { if (mSaveConfigurationOnClose) SaveConfiguration(); } //================================================================ */ //================================================================ void WxGimmick::OnItemActivated(wxTreeEvent& event) { event.Skip(); return; wxBusyCursor busy; // std::cout << "OnItemActivated" <IsExpanded(itemId)) { mTreeListCtrl->Collapse(itemId); } else { mTreeListCtrl->Expand(itemId); } } //================================================================ //================================================================ void WxGimmick::LoadChildren(wxTreeItemId& id) { TreeItemData *item = (TreeItemData *)mTreeListCtrl->GetItemData(id); if (item) { if ( ( item->IsDicomNode() || item->IsDatabase() ) && ( ! item->GetDicomNode()->ChildrenLoaded() ) ) { // If children not already loaded : do it if ( item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren (item->GetDicomNode(),item->GetDicomNode()->GetType()+1) > 0 ) { // Some new children loaded // Sort them if (mSettings.HasActiveComparator (item->GetDicomNode()->GetType()+1)) { /* std::cout << "Sorting using '" << mSettings.GetActiveComparator (item->GetDicomNode()->GetType()+1).GetName() << "' ... "; */ item->GetDicomNode()->SortChildren ( mSettings.GetActiveComparator (item->GetDicomNode()->GetType()+1) ); // std::cout << "ok"<GetDicomNode()->GetChildrenList().begin(); i!=item->GetDicomNode()->GetChildrenList().end(); i++) { UpdateDicomNodeView(*i,id); } } // EO If children not already loaded } } } //================================================================ //================================================================ void WxGimmick::OnItemExpanded(wxTreeEvent& event) { // std::cout << "* Expanded *"<GetItemData(itemId); if (item) { if ( ( item->IsDicomNode() || item->IsDatabase() ) && ( ! item->GetDicomNode()->ChildrenLoaded() ) ) { // If children not already loaded : do it if ( item->GetDicomNode()->GetDicomDatabase()->DBLoadChildren (item->GetDicomNode(),item->GetDicomNode()->GetType()+1) > 0 ) { // Some new children loaded // Sort them if (mSettings.HasActiveComparator (item->GetDicomNode()->GetType()+1)) { /* std::cout << "Sorting using '" << mSettings.GetActiveComparator (item->GetDicomNode()->GetType()+1).GetName() << "' ... "; */ item->GetDicomNode()->SortChildren ( mSettings.GetActiveComparator (item->GetDicomNode()->GetType()+1) ); // std::cout << "ok"<IsDicomNode()) { if (item->GetDicomNode()->GetType()==DicomNode::Series) { // SORT LexicographicalDicomNodeComparator compare; // DicomNodeImageImageNumberComparator c1; DicomNodeImageSliceLocationComparator c1; DicomNodeImageImageNumberComparator c2; DicomNodeImageFileNameComparator cn; compare.Add(c1); compare.Add(c2); compare.Add(cn); // std::cout << "SORT"<GetDicomNode()->SortChildren(compare); // std::cout << "EO SORT"<GetDicomNode()->GetChildrenList().begin(); i!=item->GetDicomNode()->GetChildrenList().end(); i++) { UpdateDicomNodeView(*i,itemId); } } // EO If children not already loaded } } // mTreeListCtrl->Expand(itemId); } //================================================================ /* //===================================================================== void WxGimmick::InsertRoot(wxTreeItemId& id, Root* r) { wxBusyCursor busy; TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id); if (data) { wxStopWatch sw; data->GetDicomNode()->GetDicomDatabase()->LoadAll(); printf(">>>>>> Time to load all = %ldms \n",sw.Time()); UpdateRootView(data->GetDicomNode()->GetDicomDatabase()); if (data->IsDicomNode()) { wxStopWatch sw1; r->Insert(data->GetDicomNode()); printf(">>>>>> Time to insert = %ldms \n",sw1.Time()); UpdateRootView(r); } else if (data->IsDatabase()) { wxStopWatch sw1; DicomNode::ChildrenListType::iterator j; for (j= data->GetDicomNode()->GetChildrenList().begin(); j!=data->GetDicomNode()->GetChildrenList().end(); j++) { r->Insert(*j); } printf(">>>>>> Time to insert = %ldms \n",sw1.Time()); UpdateRootView(r); } } } //===================================================================== */ //================================================= void WxGimmick::DeleteDicomDatabase(wxTreeItemId& id, DicomDatabase* db) { wxBusyCursor busy; DicomDatabaseListType::iterator i = find(GetDicomDatabaseList().begin(), GetDicomDatabaseList().end(), db); delete (*i); GetDicomDatabaseList().erase(i); mTreeListCtrl->Delete(id); } //================================================= //===================================================================== void WxGimmick::OnItemRightClick(wxTreeEvent& event) { wxTreeItemId itemId = event.GetItem(); if (itemId.IsOk()) { wxPoint clientpt = event.GetPoint(); wxPoint screenpt = ClientToScreen(clientpt); ShowMenu(itemId, clientpt); } event.Skip(); } //===================================================================== //===================================================================== void WxGimmick::ShowMenu(wxTreeItemId id, const wxPoint& pt) { // std::cout << "ShowMenu" <GetItemData(id); /* wxString title; if ( id.IsOk() ) { title << wxT("Menu for ") << mTreeListCtrl->GetItemText(id); } else { title = wxT("Menu for no particular item"); } */ #if wxUSE_MENUS wxMenu menu; if (id==mCollectionsTitlesItemId) { menu.Append(PopUp_NewCollection, _T("&New collection")); menu.Append(PopUp_OpenCollection, _T("&Open collection")); } if (data) { if (data->IsDatabase()) { wxMenu* addmenu = new wxMenu; addmenu->Append(PopUp_AddDirectory, _T("Scan &Directory")); addmenu->Append(PopUp_AddFile, _T("Select &File(s)")); // addmenu->Append(PopUp_AddRawFile, _T("Add &Raw image")); menu.AppendSubMenu(addmenu, _T("&Add image(s) to collection...")); menu.Append(PopUp_CloseCollection, _T("&Close collection")); menu.Append(PopUp_DeleteCollection, _T("&Delete collection")); } if (data->IsDicomNode()) { // LG : BUGGY /* std::string str("&Remove "); str += data->GetDicomNode()->GetTypeName(); menu.Append(PopUp_Remove, std2wx(str)); */ } if ((data->GetDicomNode()>0)&& ( data->GetDicomNode()->GetType()GetDicomNode()->GetType()+1; if (mSettings.HasActiveComparator(ctype)) { wxMenu* sortmenu = new wxMenu; int n = 0; Settings::ComparatorsList::iterator i; for (i =mSettings.GetComparatorsList(ctype).begin(); i !=mSettings.GetComparatorsList(ctype).end(); ++i) { sortmenu->AppendRadioItem(PopUp_Sort+n, std2wx(i->GetName())); n++; } sortmenu->Check(PopUp_Sort+ mSettings.GetActiveComparatorIndex(ctype) ,true); std::string sortmenustr("&Sort "); sortmenustr += DicomNode::GetPluralTypeName(ctype); sortmenustr += " by..."; if (menu.GetMenuItemCount()>0) menu.AppendSeparator(); menu.AppendSubMenu(sortmenu,std2wx(sortmenustr)); /* item->GetDicomNode()->SortChildren ( mSettings.GetActiveComparator (item->GetDicomNode()->GetType()+1) ); std::cout << "ok"<GetDicomNode()); } GetEventHandler()->ProcessEvent(ev); // if (menu.GetMenuItemCount()>0) menu.AppendSeparator(); menu.Append(PopUp_Settings, wxT("&Settings...")); menu.Append(PopUp_About, wxT("&About...")); /* wxMenu* newmenu = new wxMenu; wxMenu* openmenu = new wxMenu; Tree::RootHandlerListType::iterator h; int i=0; for (h= Tree::GetRootHandlerList().begin(); h!=Tree::GetRootHandlerList().end(); h++) { if ((*h)->SupportsNew()) { newmenu->Append(PopUp_New+i, std2wx((*h)->GetName())); } if ((*h)->SupportsOpen()) openmenu->Append(PopUp_Open+i, std2wx((*h)->GetName())); i++; } menu.AppendSubMenu(openmenu, _T("&Open")); menu.AppendSubMenu(newmenu, _T("&New")); if (data) { if ((data->IsDatabase())||(data->IsDicomNode())) { Root* itroot = data->GetDicomNode()->GetDicomDatabase(); // if (!itroot) itroot = data->GetDicomNode()->GetRoot(); wxMenu* insertmenu = new wxMenu; bool hasone = false; i = 0; Tree::RootListType::iterator j; for (j = mTree->GetDatabaseList().begin(); j != mTree->GetDatabaseList().end(); j++) { // std::cout << (*j)->GetName() << " " // << (*j)->GetTypeName() // << " i="<<(*j)->SupportsInsert()<SupportsInsert()) ) { insertmenu->Append(PopUp_Insert+i, std2wx((*j)->GetName())); hasone = true; } i++; } if (hasone) menu.AppendSubMenu(insertmenu, _T("&Insert into")); } if (data->IsDatabase()) { menu.Append(PopUp_Close, wxT("&Close")); } if (data->IsDicomNode() && data->GetDicomNode()->GetDicomDatabase()->SupportsRemove()) { menu.Append(PopUp_Remove, wxT("&Remove")); } } */ PopupMenu(&menu, pt); #endif // wxUSE_MENUS // std::cout << "EO ShowMenu" <ShowModal(); delete s; } //===================================================================== //===================================================================== void WxGimmick::OnPopUpNewCollection(wxCommandEvent& event) { wxBusyCursor busy; OpenOrNewDatabase(false); } //===================================================================== //===================================================================== void WxGimmick::OnPopUpOpenCollection(wxCommandEvent& event) { wxBusyCursor busy; OpenOrNewDatabase(true); } //===================================================================== //===================================================================== void WxGimmick::OnPopUpCloseCollection(wxCommandEvent& event) { 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; wxBusyCursor busy; // std::cout << "OnPopUpClose"<GetItemData(mItemOfMenu); DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase(); // std::cout << "OnPopUpClose '"<GetName()<<"'"<GetItemData(mItemOfMenu); DicomDatabase* r = data->GetDicomNode()->GetDicomDatabase(); wxRemoveFile(std2wx(r->GetFileName())); // std::cout << "OnPopUpClose '"<GetName()<<"'"<ShowModal()==wxID_OK) { wxBusyCursor busy; mCurrentDirectory = FD->GetDirectory(); wxArrayString files; FD->GetPaths(files); unsigned int i; std::vector filenames; for (i=0;iGetItemData(mItemOfMenu); DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase(); DicomDatabase::UpdateSummary summary; wxProgressDialog* progress = new wxProgressDialog(_T("Adding file(s)"), _T(""), 1000, this, wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME | wxPD_CAN_ABORT ); db->AddFiles(filenames,progress,summary); progress->Pulse(_T("Updating view...")); UpdateDicomDatabaseView(db); delete progress; DisplayUpdateSummary(summary,this); } } //===================================================================== //===================================================================== void WxGimmick::OnPopUpAddRawFile(wxCommandEvent& event) { wxMessageBox(_T("Not yet implemented !"),_T("Sorry"),wxOK,this); } //===================================================================== //===================================================================== void WxGimmick::OnPopUpAddDirectory(wxCommandEvent& event) { long style = wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST; wxDirDialog* FD = new wxDirDialog( 0, _T("Select directory"), mCurrentDirectory, style); if (FD->ShowModal()==wxID_OK) { bool recurse = false; if (wxMessageBox(_T("Recurse into sub-directories ?"), _T("Scan directory"), wxYES_NO,this ) == wxYES) { recurse = true; } wxBusyCursor busy; wxProgressDialog* progress = new wxProgressDialog(_T("Scanning directory"), _T("Parsing directory"), 1000, this, wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME | wxPD_CAN_ABORT ); DicomDatabase::UpdateSummary summary; std::string dirname = wx2std (FD->GetPath()) ; mCurrentDirectory = FD->GetPath(); TreeItemData *data = (TreeItemData *) mTreeListCtrl->GetItemData(mItemOfMenu); DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase(); db->AddDirectory(dirname,recurse,progress,summary); progress->Pulse(_T("Updating view...")); UpdateDicomDatabaseView(db); delete progress; DisplayUpdateSummary(summary,this); /* if (summary.cancelled_by_user) { std::cout << "!! Cancelled by user !!"<GetItemData(mItemOfMenu); std::string mess("Remove "); mess += data->GetDicomNode()->GetTypeName(); mess += " from collection ?"; int answer = wxMessageBox(std2wx(mess), _T("Confirm"), wxYES_NO); if (answer == wxNO) return; if ( mTreeListCtrl->IsSelected(mItemOfMenu) ) { wxTreeItemId next = mTreeListCtrl->GetNextSibling(mItemOfMenu); if (next.IsOk()) { mTreeListCtrl->SelectItem(next); } else { return; } } DicomDatabase* db = data->GetDicomNode()->GetDicomDatabase(); db->Remove(data->GetDicomNode()); // std::cout << "OnPopUpClose '"<GetName()<<"'"<GetItemData(mItemOfMenu); int index = event.GetId() - PopUp_Sort; DicomNode* node = data->GetDicomNode(); DicomNode::Type ctype = node->GetType()+1; mSettings.SetActiveComparatorIndex(ctype,index); if (node->ChildrenLoaded()) { // Remove children mTreeListCtrl->DeleteChildren(mItemOfMenu); /* std::cout << "Sorting using '" << mSettings.GetActiveComparator(ctype).GetName() << "' ... "; */ node->SortChildren ( mSettings.GetActiveComparator(ctype) ); // std::cout << "ok"<GetChildrenList().begin(); i!=node->GetChildrenList().end(); i++) { UpdateDicomNodeView(*i,mItemOfMenu); } } } //===================================================================== //===================================================================== void WxGimmick::OnPopUpUser(wxCommandEvent& event) { // std::cout << "OnPopUpUser"<SetImageList(NULL); return; } if ( size == 0 ) size = m_imageSize; else m_imageSize = size; wxIcon icons[20]; // should correspond to Icon_xxx enum icons[Icon_Patient] = wxIcon(patient_xpm); icons[Icon_Study] = wxIcon(study_xpm); icons[Icon_Series] = wxIcon(series_xpm); icons[Icon_Image] = wxIcon(image_xpm); icons[Icon_Database] = wxIcon(database_xpm); icons[Icon_Folder] = wxIcon(folder_xpm); icons[Icon_DicomDir] = wxIcon(dicomdir_xpm); icons[Icon_Root] = wxIcon(root_xpm); // mFirstRootIconIndex = 8; // int i=0; /* Tree::RootHandlerListType::iterator h; for (h= Tree::GetDatabaseHandlerList().begin(); h!=Tree::GetDatabaseHandlerList().end(); h++) { icons[mFirstRootIconIndex+i] = (*h)->GetIcon(); i++; } */ unsigned int NbIcons = 8;//mFirstRootIconIndex + i; // Make an image list containing small icons wxImageList *images = new wxImageList(size, size, true); int sizeOrig = icons[0].GetWidth(); for ( size_t i = 0; i < NbIcons; i++ ) { if ( size == sizeOrig ) { images->Add(icons[i]); } else { images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size))); } } mTreeListCtrl->AssignImageList(images); } //================================================= //================================================================ bool WxGimmick::IsImageSelectable(DicomNode* node) { int rows = node->ImageGetRows(); int cols = node->ImageGetColumns(); int frms = node->ImageGetFrames(); // std::cout << "R/C/F = " << rows << "/"<< cols <<"/"<0) dim=3; else if (cols>0) dim=2; else if (rows>0) dim=1; if (dim == 0) { std::cout << "Unknown image dimension : cannot select !" << std::endl; return false; } else if (dim>mSelectionMaxImageDimension) { std::cout << "Selecting "<GetSelectionSize() == 0 ) { mCurrentSelectionImageSize[0] = cols; mCurrentSelectionImageSize[1] = rows; mCurrentSelectionImageSize[2] = frms; return true; } else { if ( dim == mSelectionMaxImageDimension ) { std::cout << "Cannot add this image to selection : would result in a "<ImageGetFullFileName() << std::endl; return true; } //================================================================ //================================================================ void WxGimmick::OnSelChanging(wxTreeEvent& event) { event.Veto(); wxTreeItemId id = event.GetItem(); if (!id.IsOk()) { std::cout << "INTERNAL ERROR : ID NOT OK"<GetItemData(id); if (data->IsDicomNode()) { if (data->GetDicomNode()>0) { // An image was selected if (data->GetDicomNode()->GetType()==DicomNode::Image) { if (IsImageSelectable(data->GetDicomNode())) event.Allow(); } // A series was selected else if (data->GetDicomNode()->GetType()==DicomNode::Series) { // If images not loaded do it LoadChildren(id); // can be selected if all its images can wxTreeItemId child; wxTreeItemIdValue cookie; for (child = mTreeListCtrl->GetFirstChild(id,cookie); child.IsOk(); child = mTreeListCtrl->GetNextChild(id,cookie)) { TreeItemData *cdata = (TreeItemData *)mTreeListCtrl->GetItemData(child); if ((cdata->IsDicomNode())&& (cdata->GetDicomNode()>0)&& (cdata->GetDicomNode()->GetType()==DicomNode::Image)&& (!IsImageSelectable(cdata->GetDicomNode()))) return; } event.Allow(); } } } } //================================================================ //================================================================ void WxGimmick::OnSelChanged(wxTreeEvent& event) { // wxBusyCursor busy; // std::vector items; // GetSelectedItems(items); /* std::vector::iterator i; for (i=nodes.begin();i!=nodes.end();++i) { std::cout << "'" << (*i)->GetFieldValue("FullFileName") << "'" << std::endl; } std::cout << "++++++++++++++++++++" << std::endl; */ // ShowImage(mReader.GetImage("")); bool no_image = true; static int max = 1000; // if (items.size()>0) // { // Update image preview : send requests to the MTImageReader // bool first = true; // std::vector::iterator i; // for (i=items.begin();i!=items.end();++i) // { /* if (first) { DicomNode* node = GetDicomNodeOfItem(items[0]); if (!node) return; // Update dicom fields panel mFieldsView->UpdateValues(node); } */ wxTreeItemId item = mTreeListCtrl->GetCurrent(); DicomNode* n = GetDicomNodeOfItem(item); if (n) mFieldsView->UpdateValues(n); if ( (n!=0) && (n->GetType()==DicomNode::Image) ) { // no_image = false; //if (i==items.begin()) mCurImageItemToShow = item; int maxprio = mReader.GetMaximalPriority(); int prio = maxprio + 1000; wxTreeItemId sib = item; //GetTreeListCtrl()->GetNextSibling(*i); while (sib.IsOk()) { DicomNode* nsib = GetDicomNodeOfItem(sib); if (nsib>0) { // std::cout << "-- Request '" // << nsib->GetFieldValue("FullFileName") // << "' prio="<ImageGetFullFileName(), prio); mImageFileNameToNode[nsib->ImageGetFullFileName()] = nsib; prio--; } sib = GetTreeListCtrl()->GetNextSibling(sib); } prio = maxprio + 1000; sib = GetTreeListCtrl()->GetPrevSibling(item); while (sib.IsOk()) { DicomNode* nsib = GetDicomNodeOfItem(sib); if (nsib>0) { // std::cout << "-- Request '" // << nsib->GetFieldValue("FullFileName") // << "' prio="<ImageGetFullFileName(), prio); mImageFileNameToNode[nsib->ImageGetFullFileName()] = nsib; prio--; } sib = GetTreeListCtrl()->GetPrevSibling(sib); } // mImageFileNameToNode[n->GetFieldValue("FullFileName")] = n; max += 1000; ProcessImageEvents(); } // std::cout << "* Selection changed * (im)"<ProcessEvent(ev); if (no_image) ShowImage(mReader.GetImage("")); } //================================================================ //================================================================ void WxGimmick::ShowImage(vtkImageData* im) { // wxBusyCursor busy; int x1,x2,y1,y2,z1,z2; double spx,spy,spz; im->GetSpacing(spx,spy,spz); im->GetExtent (x1,x2,y1,y2,z1,z2); /* std::cout << x1 << "-"<GetRenderer()->GetActiveCamera(); camera->SetViewUp ( spx*0, -spy*1, spz*0); camera->SetPosition( spx*(x1+x2)/2, spy*(y1+y2)/2, -spz*10000000); camera->SetFocalPoint ( spx*(x1+x2)/2 , spy*(y1+y2)/2 , spz*0); camera->ComputeViewPlaneNormal(); camera->SetParallelScale( spx*(x2-x1)/2.0 ); } mViewer->SetInput( im ); mViewer->SetSlice( 0 ); mInteractor->Render(); } //================================================================ //================================================================ void WxGimmick:: OnMultiThreadImageReaderEvent(const std::string& filename, MultiThreadImageReaderUser::EventType e, vtkImageData* image) { if (filename.size()==0) { mImageEventQueue.push_back(ImageEventType(image)); return; } std::map::iterator i; i = mImageFileNameToNode.find(filename); if (i!=mImageFileNameToNode.end()) { wxTreeItemId id = i->second->GetData()->GetTreeItemData()->GetItemId(); mImageEventQueue.push_back(ImageEventType(id,image)); } } //================================================================ //================================================================ // Processes the queue of image events void WxGimmick::ProcessImageEvents() { // std::cout << "++++++++++ ProcessImageEvents " << std::endl; MultiThreadImageReaderEventLock(); while (!mImageEventQueue.empty()) { ImageEventType e = mImageEventQueue.front(); mImageEventQueue.pop_front(); if( e.image!=0 ) { if (e.item.IsOk()) { mTreeListCtrl->SetItemTextColour(e.item, mSettings.LoadedImageColour());//wxImageLoadedColour); TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(e.item); data->SetLoaded(true); if (mCurImageItemToShow == e.item) { ShowImage(e.image); } } else if (!mCurImageItemToShow.IsOk()) { ShowImage(e.image); } } else if (e.item.IsOk()) { mTreeListCtrl->SetItemTextColour(e.item,mSettings.Colour(DicomNode::Image)); //.wxImageUnloadedColour); TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(e.item); data->SetLoaded(false); } } mImageEventQueue.clear(); MultiThreadImageReaderEventUnlock(); // std::cout << "++++++++++ END ProcessImageEvents " << std::endl; } //================================================================ //================================================================ void WxGimmick::OnInternalIdle() { ProcessImageEvents(); /* if (mJustStarted) { mJustStarted = false; } */ // } //================================================================ //================================================================ // LG : For the moment any selection is valid but in the future // incomplete selections can be invalid... bool WxGimmick::IsSelectionValid() { return (mTreeListCtrl->GetSelectionSize()>0); } //================================================================ //================================================================ void WxGimmick::GetSelectedFiles(std::vector& f) { wxArrayTreeItemIds id; // TO DO : TEST THAT STYLE IS MULTIPLE unsigned int nb = mTreeListCtrl->GetSelections(id); f.clear(); for (unsigned int i=0; iGetItemData(id[i]); if ((data) && (data->IsDicomNode())) { if (data->GetDicomNode()->GetType()==DicomNode::Image) { f.push_back ( data->GetDicomNode()->ImageGetFullFileName() ); } else if (data->GetDicomNode()->GetType()==DicomNode::Series) { DicomNode::ChildrenListType::iterator j; for (j =data->GetDicomNode()->GetChildrenList().begin(); j!=data->GetDicomNode()->GetChildrenList().end(); j++) { f.push_back((*j)->ImageGetFullFileName()); } } } } } //================================================================ //================================================================ void WxGimmick::GetSelectedImages(std::vector& f) { wxArrayTreeItemIds id; // TO DO : TEST THAT STYLE IS MULTIPLE unsigned int nb = mTreeListCtrl->GetSelections(id); f.clear(); // Collect the brute vector of Image nodes std::vector im; for (unsigned int i=0; iGetItemData(id[i]); if ((data) && (data->IsDicomNode())) { if (data->GetDicomNode()->GetType()==DicomNode::Image) { im.push_back ( data->GetDicomNode() ); } else if (data->GetDicomNode()->GetType()==DicomNode::Series) { DicomNode::ChildrenListType::iterator j; for (j =data->GetDicomNode()->GetChildrenList().begin(); j!=data->GetDicomNode()->GetChildrenList().end(); j++) { im.push_back ( *j ); } } } } // Create the output data if (im.size()==1) { // Only one image : give it vtkImageData* out = vtkImageData::New(); out->ShallowCopy(mReader.GetImage(im.front()->ImageGetFullFileName())); f.push_back( out ); } else if (im.size()>1) { vtkImageData* first = mReader.GetImage( im.front()->ImageGetFullFileName() ); if (first->GetDataDimension()==2) { // n2D to 3D vtkImageData* out = vtkImageData::New(); out->CopyStructure(first); out->SetScalarType(first->GetScalarType()); int ext[6]; first->GetExtent(ext); ext[5] = im.size(); out->SetExtent(ext); // LG : TODO : Z Spacing ? out->AllocateScalars(); //first->Print(std::cout); // out->Print(std::cout); int dim[3]; first->GetDimensions(dim); unsigned long imsize = ( (unsigned long)first->GetScalarPointer(0,1,0) - (unsigned long)first->GetScalarPointer(0,0,0)) *dim[1]; int slice = 0; std::vector::iterator it; for (it=im.begin(); it!=im.end(); ++it) { //std::cout << "copying slice "<ImageGetFullFileName() ); void* src = cur->GetScalarPointer(0,0,0); void* dst = out->GetScalarPointer(0,0,slice); // std::cout << "src="<GetScalarComponentAsFloat(x,y,slice,0) << std::endl; } } */ slice++; } f.push_back(out); } else { // n3D std::vector::iterator it; for (it=im.begin(); it!=im.end(); ++it) { vtkImageData* out = vtkImageData::New(); out->ShallowCopy(mReader.GetImage((*it)->ImageGetFullFileName())); f.push_back(out); } } } } //================================================================ //================================================================ void WxGimmick::GetSelectedDicomNodes(std::vector& f) { wxArrayTreeItemIds id; // TO DO : TEST THAT STYLE IS MULTIPLE unsigned int nb = mTreeListCtrl->GetSelections(id); f.clear(); for (unsigned int i=0; iGetItemData(id[i]); if ((data) && (data->IsDicomNode())) { f.push_back ( data->GetDicomNode() ); } /* if (data->GetDicomNode()->GetType()==DicomNode::Image) { f.push_back ( data->GetDicomNode() ); //->ImageGetFullFileName() ); } else if (data->GetDicomNode()->GetType()==DicomNode::Series) { DicomNode::ChildrenListType::iterator j; for (j =data->GetDicomNode()->GetChildrenList().begin(); j!=data->GetDicomNode()->GetChildrenList().end(); j++) { f.push_back((*j)); //->ImageGetFullFileName() ); } } } */ } } //================================================================ //================================================================ void WxGimmick::GetSelectedItems(std::vector& f) { wxArrayTreeItemIds id; // TO DO : TEST THAT STYLE IS MULTIPLE unsigned int nb = mTreeListCtrl->GetSelections(id); f.clear(); for (unsigned int i=0; iGetItemData(i); if (data) return ( data->GetDicomNode() ); return 0; } //================================================================ //================================================================ //================================================================ //================================================================ //================================================================ //================================================================ //================================================================ //================================================================ //================================================================ BEGIN_EVENT_TABLE(WxGimmick, wxPanel) // POP UP MENU EVT_MENU(PopUp_NewCollection,WxGimmick::OnPopUpNewCollection) EVT_MENU(PopUp_OpenCollection,WxGimmick::OnPopUpOpenCollection) EVT_MENU(PopUp_CloseCollection,WxGimmick::OnPopUpCloseCollection) EVT_MENU(PopUp_DeleteCollection,WxGimmick::OnPopUpDeleteCollection) EVT_MENU(PopUp_AddFile, WxGimmick::OnPopUpAddFile) EVT_MENU(PopUp_AddRawFile, WxGimmick::OnPopUpAddRawFile) EVT_MENU(PopUp_AddDirectory, WxGimmick::OnPopUpAddDirectory) EVT_MENU(PopUp_Remove, WxGimmick::OnPopUpRemove) EVT_MENU(PopUp_About, WxGimmick::OnPopUpAbout) EVT_MENU(PopUp_Settings, WxGimmick::OnPopUpSettings) EVT_MENU_RANGE(PopUp_Sort, PopUp_Sort+99, WxGimmick::OnPopUpSort) EVT_MENU_RANGE(PopUp_User, PopUp_User+99, WxGimmick::OnPopUpUser) // DRAG EVT_TREE_BEGIN_DRAG(TreeListCtrlId, WxGimmick::OnBeginDrag) EVT_TREE_BEGIN_RDRAG(TreeListCtrlId, WxGimmick::OnBeginRDrag) EVT_TREE_END_DRAG(TreeListCtrlId, WxGimmick::OnEndDrag) // LABEL EVT_TREE_BEGIN_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnBeginLabelEdit) EVT_TREE_END_LABEL_EDIT(TreeListCtrlId, WxGimmick::OnEndLabelEdit) //DELETE : UNUSED EVT_TREE_DELETE_ITEM(TreeListCtrlId, WxGimmick::OnDeleteItem) #if 0 // there are so many of those that logging them causes flicker EVT_TREE_GET_INFO(TreeListCtrlId, WxGimmick::OnGetInfo) #endif // UNUSED EVT_TREE_SET_INFO(TreeListCtrlId, WxGimmick::OnSetInfo) // EXPAND/COLLAPSE EVT_TREE_ITEM_EXPANDED(TreeListCtrlId, WxGimmick::OnItemExpanded) EVT_TREE_ITEM_EXPANDING(TreeListCtrlId, WxGimmick::OnItemExpanding) EVT_TREE_ITEM_COLLAPSED(TreeListCtrlId, WxGimmick::OnItemCollapsed) EVT_TREE_ITEM_COLLAPSING(TreeListCtrlId, WxGimmick::OnItemCollapsing) // SELECTION EVT_TREE_SEL_CHANGED(TreeListCtrlId, WxGimmick::OnSelChanged) EVT_TREE_SEL_CHANGING(TreeListCtrlId, WxGimmick::OnSelChanging) // KEY EVT_TREE_KEY_DOWN(TreeListCtrlId, WxGimmick::OnTreeKeyDown) // ACTIVATION = DOUBLE CLICK OR ENTER ON SELECTED EVT_TREE_ITEM_ACTIVATED(TreeListCtrlId, WxGimmick::OnItemActivated) // so many differents ways to handle right mouse button clicks... // EVT_CONTEXT_MENU(WxGimmick::OnContextMenu) // EVT_TREE_ITEM_MENU is the preferred event for creating context menus // on a tree control, because it includes the point of the click or item, // meaning that no additional placement calculations are required. // EVT_TREE_ITEM_MENU(TreeListCtrlId, WxGimmick::OnItemMenu) EVT_TREE_ITEM_RIGHT_CLICK(TreeListCtrlId, WxGimmick::OnItemRightClick) // UNUSED // EVT_RIGHT_DOWN(WxGimmick::OnRMouseDown) // EVT_RIGHT_UP(WxGimmick::OnRMouseUp) // EVT_RIGHT_DCLICK(WxGimmick::OnRMouseDClick) END_EVENT_TABLE() //IMPLEMENT_DYNAMIC_CLASS(WxGimmick, wxTreeListCtrl) /* wxTree::wxTree(wxWindow *parent, const wxWindowID id, const wxPoint& pos, const wxSize& size, long style) : wxTreeListCtrl(parent, id, pos, size, style) { m_reverseSort = false; CreateImageList(); // Add some items to the tree AddTestItemsToTree(5, 2); } */ #if USE_GENERIC_TREECTRL || !defined(__WXMSW__) void WxGimmick::CreateButtonsImageList(int size) { /* if ( size == -1 ) { mTreeListCtrl->SetButtonsImageList(NULL); return; } // Make an image list containing small icons wxImageList *images = new wxImageList(size, size, true); // should correspond to TreeListCtrlIcon_xxx enum wxBusyCursor wait; wxIcon icons[4]; icons[0] = wxIcon(icon3_xpm); // closed icons[1] = wxIcon(icon3_xpm); // closed, selected icons[2] = wxIcon(icon5_xpm); // open icons[3] = wxIcon(icon5_xpm); // open, selected for ( size_t i = 0; i < WXSIZEOF(icons); i++ ) { int sizeOrig = icons[i].GetWidth(); if ( size == sizeOrig ) { images->Add(icons[i]); } else { images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size))); } } mTreeListCtrl->AssignButtonsImageList(images); */ #else void WxGimmick::CreateButtonsImageList(int WXUNUSED(size)) { #endif } /* int WxGimmick::OnCompareItems(const wxTreeItemId& item1, const wxTreeItemId& item2) { if ( m_reverseSort ) { // just exchange 1st and 2nd items return mTreeListCtrl->OnCompareItems(item2, item1); } else { return mTreeListCtrl->OnCompareItems(item1, item2); } } void WxGimmick::DoToggleIcon(const wxTreeItemId& item) { int image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_Folder) ? TreeIcon_File : TreeIcon_Folder; mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Normal); image = (mTreeListCtrl->GetItemImage(item) == TreeIcon_FolderSelected) ? TreeIcon_FileSelected : TreeIcon_FolderSelected; mTreeListCtrl->SetItemImage(item, image, wxTreeItemIcon_Selected); } void WxGimmick::LogEvent(const wxChar *name, const wxTreeEvent& event) { wxTreeItemId item = event.GetItem(); wxString text; if ( item.IsOk() ) text << _T('"') << mTreeListCtrl->GetItemText(item).c_str() << _T('"'); else text = _T("invalid item"); // wxLogMessage(wxT("%s(%s)"), name, text.c_str()); } */ // avoid repetition #define TREE_EVENT_HANDLER(name) \ void WxGimmick::name(wxTreeEvent& event) \ { \ /* LogEvent(_T(#name), event); */ \ /* SetLastItem(mTreeListCtrl->wxTreeItemId()) *;*/ \ event.Skip(); \ } TREE_EVENT_HANDLER(OnBeginRDrag) TREE_EVENT_HANDLER(OnDeleteItem) TREE_EVENT_HANDLER(OnGetInfo) TREE_EVENT_HANDLER(OnSetInfo) //TREE_EVENT_HANDLER(OnItemExpanded) TREE_EVENT_HANDLER(OnItemExpanding) //TREE_EVENT_HANDLER(OnItemCollapsed) //TREE_EVENT_HANDLER(OnSelChanged) // TREE_EVENT_HANDLER(OnSelChanging) void WxGimmick::OnItemCollapsed(wxTreeEvent& event) { // std::cout << "* Collapsed *"<GetSelection(); if (itemId.IsOk()) { std::cout << "item is ok"<GetItemData(id); // std::cout << "OnBeginDrag("<IsDatabase()) { // std::cout << "-- IS ROOT"<IsDicomNode()) { // std::cout << "-- IS NODE"<GetItemData(id); if (data->IsDatabase()) { // std::cout << "-- IS ROOT"<IsDicomNode()) { // std::cout << "-- IS NODE"<GetItemData(id); // If not a root : veto if (data->IsDatabase()) { event.Allow(); return; } event.Veto(); } //==================================================================== //==================================================================== void WxGimmick::OnEndLabelEdit(wxTreeEvent& event) { // std::cout << "OnEndLabelEdit"<IsDatabase()) { data->GetDicomNode()->GetDicomDatabase()->SetName(wx2std(event.GetLabel())); mFieldsView->UpdateValues(data->GetDicomNode()); } else { std::cerr<< "!!!! Internal error : send bug report !!!!"<CenterOnParent(); mHelpWindow->ShowModal(); */ } //==================================================================== //================================================================ //================================================================ //================================================================ //================================================================ //================================================================ // WxGimmickEvent //================================================================ //================================================================ //================================================================ //================================================================ //================================================================ // ---------------------------------------------------------------------------- // events // ---------------------------------------------------------------------------- /* DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_DRAG) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_RDRAG) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_DELETE_ITEM) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_GET_INFO) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_SET_INFO) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_EXPANDING) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_COLLAPSING) */ DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_LABEL_EDIT) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_SEL_CHANGING) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_KEY_DOWN) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_CONTEXTUAL_MENU) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREEVIEWLIST_ITEM_STYLE_CHANGED) /* DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_ACTIVATED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_END_DRAG) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP) DEFINE_EVENT_TYPE(wxEVT_COMMAND_TREE_ITEM_MENU) */ // ---------------------------------------------------------------------------- // Tree event // ---------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(WxGimmickEvent, wxNotifyEvent) WxGimmickEvent::WxGimmickEvent(wxEventType commandType, WxGimmick *tree, const wxTreeItemId& item) : wxNotifyEvent(commandType, tree->GetId()), m_item(item), mDicomNode(0) { // m_editCancelled = false; SetEventObject(tree); if ( item.IsOk() ) SetClientObject(tree->mTreeListCtrl->GetItemData(item)); } WxGimmickEvent::WxGimmickEvent(wxEventType commandType, int id) : wxNotifyEvent(commandType, id), mDicomNode(0) { m_itemOld = 0l; // m_editCancelled = false; } WxGimmickEvent::WxGimmickEvent(const WxGimmickEvent & event) : wxNotifyEvent(event), mDicomNode(0) { m_evtKey = event.m_evtKey; m_item = event.m_item; m_itemOld = event.m_itemOld; mColor = event.mColor; mUserData = event.mUserData; // m_pointDrag = event.m_pointDrag; // m_label = event.m_label; // m_editCancelled = event.m_editCancelled; } //================================================================ //================================================================ //================================================================ //================================================================ //================================================================ WxGimmickFrame::WxGimmickFrame( wxWindow *parent, wxString title, wxSize size) : wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size) { wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); mWxGimmick = new WxGimmick(this,-1, wxDefaultPosition, wxDefaultSize); sizer->Add(mWxGimmick,1,wxGROW); SetSizer(sizer); SetAutoLayout(true); Layout(); } //================================================================ //================================================================ WxGimmickFrame::~WxGimmickFrame() { } //================================================================ //================================================================ void WxGimmickFrame::OnSelChanged(WxGimmickEvent& event) { // std::cout << "+++++ WxGimmickFrame::OnSelChanged ++++++++++" // < file; // mWxGimmick->GetSelectedImages(file); /* std::vector::iterator i; for (i=file.begin();i!=file.end();++i) { std::cout << "'" << *i << "'" << std::endl; } std::cout << "++++++++++++++++++++" << std::endl; */ } //================================================================ //================================================================ BEGIN_EVENT_TABLE(WxGimmickFrame, wxFrame) EVT_TREEVIEWLIST_SEL_CHANGED(-1,WxGimmickFrame::OnSelChanged) END_EVENT_TABLE() //================================================================ }