//================================================================
//================================================================
WxGimmick::WxGimmick(wxWindow *parent,
- wxWindowID id,
- const wxPoint& pos,
- const wxSize& size,
- int threads)
+ 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();
}
//================================================================
+ //================================================================
+ 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"<<std::endl;
+ }
+ // Update tree
+ DicomNode::ChildrenListType::iterator i;
+ for (i=item->GetDicomNode()->GetChildrenList().begin();
+ i!=item->GetDicomNode()->GetChildrenList().end();
+ i++)
+ {
+ UpdateDicomNodeView(*i,id);
+ }
+ }
+ // EO If children not already loaded
+ }
+ }
+ }
+ //================================================================
+
+
//================================================================
void WxGimmick::OnItemExpanded(wxTreeEvent& event)
{
wxBusyCursor busy;
wxTreeItemId itemId = event.GetItem();
-
+ LoadChildren(itemId);
+
+ return;
+
// expand if collapsed and collapse if expanded ...
TreeItemData *item =
(TreeItemData *)mTreeListCtrl->GetItemData(itemId);
}
//=================================================
+
+
+
+
+
+
+
+ //================================================================
+ bool WxGimmick::IsImageSelectable(DicomNode* node)
+ {
+ int rows = node->ImageGetRows();
+ int cols = node->ImageGetColumns();
+ int frms = node->ImageGetFrames();
+
+ // std::cout << "R/C/F = " << rows << "/"<< cols <<"/"<<frms<<std::endl;
+
+ int dim = 0;
+ if (frms>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 "<<dim<<"D images is not allowed !"
+ << std::endl;
+ return false;
+ }
+
+ if ( mTreeListCtrl->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 "<<dim+1<<"D image !" << std::endl;
+ return false;
+ }
+ if ( ( cols != mCurrentSelectionImageSize[0] ) ||
+ ( rows != mCurrentSelectionImageSize[1] ) ||
+ ( frms != mCurrentSelectionImageSize[2] ) )
+ {
+ std::cout << "Cannot add this image to selection : image size is incomptatible with currently selected images" << std::endl;
+ return false;
+ }
+ }
+ std::cout << "Selecting : "<<node->ImageGetFullFileName() << std::endl;
+ return true;
+ }
+ //================================================================
+
//================================================================
void WxGimmick::OnSelChanging(wxTreeEvent& event)
{
+ event.Veto();
wxTreeItemId id = event.GetItem();
if (!id.IsOk())
{
- std::cout << "ERROR : ID NOT OK"<<std::endl;
+ std::cout << "INTERNAL ERROR : ID NOT OK"<<std::endl;
return;
}
- TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
- event.Veto();
+ TreeItemData *data = (TreeItemData *)mTreeListCtrl->GetItemData(id);
if (data->IsDicomNode())
{
- if ((data->GetDicomNode()>0)&&
- ( data->GetDicomNode()->GetType()==DicomNode::Image))
+ if (data->GetDicomNode()>0)
{
- event.Allow();
+ // 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();
+ }
}
}
}
// << nsib->GetFieldValue("FullFileName")
// << "' prio="<<prio<<std::endl;
mReader.Request(this,
- nsib->GetFieldValue("FullFileName"),
+ nsib->ImageGetFullFileName(),
prio);
- mImageFileNameToNode[nsib->GetFieldValue("FullFileName")] =
+ mImageFileNameToNode[nsib->ImageGetFullFileName()] =
nsib;
prio--;
}
// << nsib->GetFieldValue("FullFileName")
// << "' prio="<<prio<<std::endl;
mReader.Request(this,
- nsib->GetFieldValue("FullFileName"),
+ nsib->ImageGetFullFileName(),
prio);
- mImageFileNameToNode[nsib->GetFieldValue("FullFileName")] =
+ mImageFileNameToNode[nsib->ImageGetFullFileName()] =
nsib;
prio--;
}
//================================================================
+ //================================================================
+ // 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::GetSelectedImages(std::vector<std::string>& f)
+ void WxGimmick::GetSelectedFiles(std::vector<std::string>& f)
{
wxArrayTreeItemIds id;
// TO DO : TEST THAT STYLE IS MULTIPLE
{
if (data->GetDicomNode()->GetType()==DicomNode::Image)
{
- f.push_back ( data->GetDicomNode()->GetFieldValue("FullFileName") );
+ f.push_back ( data->GetDicomNode()->ImageGetFullFileName() );
}
else if (data->GetDicomNode()->GetType()==DicomNode::Series)
{
j!=data->GetDicomNode()->GetChildrenList().end();
j++)
{
- f.push_back((*j)->GetFieldValue("FullFileName"));
+ f.push_back((*j)->ImageGetFullFileName());
}
}
}
}
//================================================================
+ //================================================================
+ void WxGimmick::GetSelectedImages(std::vector<vtkImageData*>& 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<DicomNode*> im;
+ for (unsigned int i=0; i<nb; ++i)
+ {
+ TreeItemData *data =
+ (TreeItemData *)mTreeListCtrl->GetItemData(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);
+ int ext[6];
+ first->GetExtent(ext);
+ ext[5] = im.size();
+ out->SetExtent(ext);
+
+ out->AllocateScalars();
+ 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];
+ std::cout << "imsize="<<imsize<<std::endl;
+
+ int slice = 0;
+ std::vector<DicomNode*>::iterator it;
+ for (it=im.begin(); it!=im.end(); ++it)
+ {
+ vtkImageData* cur = mReader.GetImage( (*it)->ImageGetFullFileName() );
+
+ void* src = cur->GetScalarPointer(0,0,0);
+ void* dst = out->GetScalarPointer(0,0,slice);
+ memcpy(dst,src,imsize);
+ slice++;
+ }
+ f.push_back(out);
+ }
+ else
+ {
+ // n3D
+ std::vector<DicomNode*>::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<DicomNode*>& f)
if (data->GetDicomNode()->GetType()==DicomNode::Image)
{
- f.push_back ( data->GetDicomNode() ); //->GetFieldValue("FullFileName") );
+ f.push_back ( data->GetDicomNode() ); //->ImageGetFullFileName() );
}
else if (data->GetDicomNode()->GetType()==DicomNode::Series)
{
j!=data->GetDicomNode()->GetChildrenList().end();
j++)
{
- f.push_back((*j)); //->GetFieldValue("FullFileName"));
- }
+ f.push_back((*j)); //->ImageGetFullFileName() ); }
}
}
*/
//================================================================
//================================================================
WxGimmickFrame::WxGimmickFrame( wxWindow *parent,
- wxString title,
- wxSize size)
+ wxString title,
+ wxSize size)
: wxFrame((wxFrame *)parent, -1, title, wxDefaultPosition, size)
{
wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
- long style = wxTR_DEFAULT_STYLE |
-#ifndef NO_VARIABLE_HEIGHT
- wxTR_HAS_VARIABLE_ROW_HEIGHT |
-#endif
- wxTR_EDIT_LABELS | wxSUNKEN_BORDER;
- mWxGimmick = new WxGimmick(this,-1,wxDefaultPosition,wxDefaultSize,style);
+ mWxGimmick = new WxGimmick(this,-1,
+ wxDefaultPosition,
+ wxDefaultSize);
sizer->Add(mWxGimmick,1,wxGROW);
SetSizer(sizer);
SetAutoLayout(true);
class WxGimmickDicomNodeData;
//====================================================================
+#define GIMMICK_NO_IMAGE_SELECTION 0
+#define GIMMICK_2D_IMAGE_SELECTION 2
+#define GIMMICK_3D_IMAGE_SELECTION 3
+#define GIMMICK_4D_IMAGE_SELECTION 4
+
//====================================================================
class CREAIMAGEIO_EXPORT WxGimmick : public wxPanel,
- public MultiThreadImageReaderUser
+ public MultiThreadImageReaderUser
{
public:
+
WxGimmick(wxWindow *parent, const wxWindowID id,
- const wxPoint& pos, const wxSize& size,
- int number_of_threads = 0);
+ const wxPoint& pos, const wxSize& size,
+ int image_type = GIMMICK_3D_IMAGE_SELECTION,
+ int number_of_threads = 0);
virtual ~WxGimmick();
+ int GetSelectionSize() { return mTreeListCtrl->GetSelectionSize(); }
+ bool IsSelectionValid();
+ void GetSelectedFiles(std::vector<std::string>&);
+ void GetSelectedImages(std::vector<vtkImageData*>&);
+ void GetSelectedDicomNodes(std::vector<DicomNode*>&);
+ void GetSelectedItems(std::vector<wxTreeItemId>&);
+ DicomNode* GetDicomNodeOfItem(const wxTreeItemId& i);
+
+ static const int UserMenuFirstId;
+
+ typedef WxGimmickSettings Settings;
+ const Settings& GetSettings() const { return mSettings; }
+ Settings& GetSettings() { return mSettings; }
+
+ typedef WxGimmickEvent EventType;
+
typedef std::vector<DicomDatabase*> DicomDatabaseListType;
- DicomDatabaseListType& GetDicomDatabaseList() { return mDicomDatabaseList; }
- const DicomDatabaseListType& GetDicomDatabaseList() const { return mDicomDatabaseList; }
+ DicomDatabaseListType& GetDicomDatabaseList()
+ { return mDicomDatabaseList; }
+ const DicomDatabaseListType& GetDicomDatabaseList() const
+ { return mDicomDatabaseList; }
wxTreeListCtrl* GetTreeListCtrl() { return mTreeListCtrl; }
const wxTreeListCtrl* GetTreeListCtrl() const { return mTreeListCtrl; }
void SetConfigurationFile(const std::string& filename)
- {
- mConfigurationFile = filename;
- }
+ { mConfigurationFile = filename;}
void LoadConfiguration();
void SaveConfiguration();
void SetSaveConfigurationOnClose(bool v)
{ mSaveConfigurationOnClose = v; }
- void GetSelectedImages(std::vector<std::string>&);
- void GetSelectedDicomNodes(std::vector<DicomNode*>&);
- void GetSelectedItems(std::vector<wxTreeItemId>&);
- DicomNode* GetDicomNodeOfItem(const wxTreeItemId& i);
-
-
- static const int UserMenuFirstId;
-
- typedef WxGimmickSettings Settings;
- const Settings& GetSettings() const { return mSettings; }
- Settings& GetSettings() { return mSettings; }
-
- typedef WxGimmickEvent EventType;
protected:
void RebuildView();
void InsertDicomDatabase(wxTreeItemId& id, DicomDatabase* r);
void DeleteDicomDatabase(wxTreeItemId& id, DicomDatabase* r);
+ void LoadChildren( wxTreeItemId& id );
friend class WxGimmickEvent;
private:
WxGimmick() { }
WxGimmick(const WxGimmick& ) { }
+ int mSelectionType;
+ int mSelectionMaxImageDimension;
+ int mCurrentSelectionImageSize[4];
+
DicomDatabaseListType mDicomDatabaseList;
wxTreeListCtrl* mTreeListCtrl;
void OnItemCollapsing(wxTreeEvent& event);
void OnSelChanged(wxTreeEvent& event);
void OnSelChanging(wxTreeEvent& event);
+ bool IsImageSelectable(DicomNode* node);
void OnTreeKeyDown(wxTreeEvent& event);
void OnItemActivated(wxTreeEvent& event);
void OnItemRightClick(wxTreeEvent& event);