//---------------------------------------------------------------------------- // EgalTech 2013-2014 //---------------------------------------------------------------------------- // File : GeomDbTree.cpp Data : 29.01.14 Versione : 1.5b8 // Contenuto : Metodi del dialogo principale per albero di GeomDB. // // // // Modifiche : 27.02.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "TestEGrDlg.h" #include "resource.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkGdbIterator.h" #include "/EgtDev/Include/EGkCurveLine.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EgtStringConverter.h" using namespace std ; //---------------------------------------------------------------------------- #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //--------------------------- Constants -------------------------------------- // indici icone per Tree enum { ICO_MATERS = 0, ICO_ONEMATER, ICO_NOGEO, ICO_GROUP, ICO_VECTOR, ICO_POINT, ICO_FRAME, ICO_LINE, ICO_ARC, ICO_CBEZIER, ICO_CCOMPO, ICO_STRIMESH, ICO_TEXT} ; // costanti per materiali custom/ geometrie static const int GEOM = 0x0000000 ; static const int CMAT = 0x1000000 ; //---------------------------------------------------------------------------- bool CTestEGrDlg::PrepareTree( void) { // collego l'oggetto al control m_Tree.SubclassDlgItem( IDC_TREE, this) ; // carico le immagini m_pImgList = new CImageList ; if ( m_pImgList == nullptr) return false ; m_pImgList->Create( 16, 16, ILC_COLOR, 10, 4) ; m_pImgList->Add( AfxGetApp()->LoadIcon( IDI_MATERS)) ; m_pImgList->Add( AfxGetApp()->LoadIcon( IDI_ONEMATER)) ; m_pImgList->Add( AfxGetApp()->LoadIcon( IDI_NOGEO)) ; m_pImgList->Add( AfxGetApp()->LoadIcon( IDI_GROUP)) ; m_pImgList->Add( AfxGetApp()->LoadIcon( IDI_VECTOR)) ; m_pImgList->Add( AfxGetApp()->LoadIcon( IDI_POINT)) ; m_pImgList->Add( AfxGetApp()->LoadIcon( IDI_FRAME)) ; m_pImgList->Add( AfxGetApp()->LoadIcon( IDI_LINE)) ; m_pImgList->Add( AfxGetApp()->LoadIcon( IDI_ARC)) ; m_pImgList->Add( AfxGetApp()->LoadIcon( IDI_CBEZIER)) ; m_pImgList->Add( AfxGetApp()->LoadIcon( IDI_CCOMPO)) ; m_pImgList->Add( AfxGetApp()->LoadIcon( IDI_STRIMESH)) ; m_pImgList->Add( AfxGetApp()->LoadIcon( IDI_TEXT)) ; m_Tree.SetImageList( m_pImgList, TVSIL_NORMAL) ; return true ; } //---------------------------------------------------------------------------- bool CTestEGrDlg::ClearTree( void) { // ripristino stato eventuale ultimo oggetto selezionato RevertOldIdInTree() ; // disabilito aggiornamento m_Tree.SetRedraw( FALSE) ; // svuoto l'albero m_Tree.SelectItem( NULL) ; m_Tree.DeleteAllItems() ; OutData( "") ; // riabilito aggiornamento m_Tree.SetRedraw( TRUE) ; m_Tree.Invalidate() ; return true ; } //---------------------------------------------------------------------------- bool CTestEGrDlg::LoadTree( void) { // pulisco l'albero vecchio ClearTree() ; // disabilito aggiornamento m_Tree.SetRedraw( FALSE) ; // ciclo sui materiali custom InsertCustomMaterialsInTree() ; // ciclo su GeomDB InsertGroupInTree( GDB_ID_ROOT, TVI_ROOT) ; // riabilito aggiornamento m_Tree.SetRedraw( TRUE) ; m_Tree.Invalidate() ; return true ; } //---------------------------------------------------------------------------- bool CTestEGrDlg::InsertCustomMaterialsInTree( void) { // inserisco la radice dei materiali custom HTREEITEM hMaters ; hMaters = m_Tree.InsertItem( L"Custom Materials", ICO_MATERS, ICO_MATERS, TVI_ROOT) ; if ( hMaters == nullptr || m_Tree.SetItemData( hMaters, CMAT | 0) == 0) return false ; // inserisco i materiali custom for ( int i = 1 ; i <= m_pGeomDB->GetMaxMaterialId() ; ++i) { bool bCustom ; if ( m_pGeomDB->IsCustomMaterial( i, bCustom) && bCustom) { string sName ; m_pGeomDB->GetMaterialName( i, sName) ; HTREEITEM hOneMater ; hOneMater = m_Tree.InsertItem( stringtoW( sName), ICO_ONEMATER, ICO_ONEMATER, hMaters) ; if ( hOneMater == nullptr || m_Tree.SetItemData( hOneMater, CMAT | i) == 0) return false ; } } return true ; } //---------------------------------------------------------------------------- bool CTestEGrDlg::InsertGroupInTree( int nId, HTREEITEM hParent) { // inserisco il gruppo nell'albero (se non è la radice) string sGroup ; HTREEITEM hGroup ; if ( nId == GDB_ID_ROOT) hGroup = hParent ; else { string sName ; if ( m_pGeomDB->GetName( nId, sName)) sGroup += sName + " (Group " + ToString( nId) +")" ; else sGroup = "Group " + ToString( nId) ; hGroup = m_Tree.InsertItem( stringtoW( sGroup), ICO_GROUP, ICO_GROUP, hParent) ; if ( hGroup == nullptr || m_Tree.SetItemData( hGroup, nId) == 0) return false ; } // Se troppi figli, non li visualizzo int nObjs = m_pGeomDB->GetGroupObjs( nId) ; if ( nObjs > 20000) { string sInfo = sGroup + " Too many objects ..." ; m_Tree.SetItemText( hGroup, stringtoW( sInfo)) ; return true ; } // creo un iteratore PtrOwner pIter( CreateGdbIterator()) ; if ( IsNull( pIter)) return false ; // scandisco il gruppo pIter->SetGDB( m_pGeomDB) ; bool bNext = pIter->GoToFirstInGroup( nId) ; while ( bNext) { // leggo il tipo di nodo int nGdbType = pIter->GetGdbType() ; // se gruppo if ( nGdbType == GDB_TY_GROUP) { // lo inserisco nell'albero if ( ! InsertGroupInTree( pIter->GetId(), hGroup)) return false ; } // se oggetto geometrico else if ( nGdbType == GDB_TY_GEO) { // lo inserisco nell'albero if ( ! InsertGeoObjInTree( pIter->GetId(), pIter->GetGeoObj(), hGroup)) return false ; } // passo al successivo bNext = pIter->GoToNext() ; } return true ; } //---------------------------------------------------------------------------- bool CTestEGrDlg::InsertGeoObjInTree( int nId, IGeoObj* pGeoObj, HTREEITEM hParent) { int nImage ; string sObj ; if ( pGeoObj != nullptr) { string sName ; if ( m_pGeomDB->GetName( nId, sName)) sObj += sName + " (" + pGeoObj->GetTitle() + " " + ToString( nId) +")" ; else sObj = pGeoObj->GetTitle() + " " + ToString( nId) ; nImage = GetGeoObjImage( pGeoObj->GetType()) ; } else { nImage = ICO_NOGEO ; sObj = "Null " + ToString( nId) ; } HTREEITEM hItem = m_Tree.InsertItem( stringtoW( sObj), nImage, nImage, hParent) ; return ( hItem != nullptr && m_Tree.SetItemData( hItem, nId) != 0) ; } //---------------------------------------------------------------------------- int CTestEGrDlg::GetGeoObjImage( int nType) { switch ( nType) { case GEO_VECT3D : return ICO_VECTOR ; case GEO_PNT3D : return ICO_POINT ; case GEO_FRAME3D : return ICO_FRAME ; case CRV_LINE : return ICO_LINE ; case CRV_ARC : return ICO_ARC ; case CRV_BEZ : return ICO_CBEZIER ; case CRV_COMPO : return ICO_CCOMPO ; case SRF_TRIMESH : return ICO_STRIMESH ; case EXT_TEXT : return ICO_TEXT ; } return ICO_NOGEO ; } //---------------------------------------------------------------------------- void CTestEGrDlg::OnTreeSelChanged( NMHDR* pNMHDR, LRESULT* pResult) { // assegno il risultato *pResult = 0 ; // verifiche sul DB geometrico if ( m_pGeomDB == nullptr) return ; // puntatore ai dati dell'albero LPNMTREEVIEW pNMTreeView = reinterpret_cast( pNMHDR) ; if ( pNMTreeView == nullptr) return ; // recupero l'Id del nuovo oggetto selezionato HTREEITEM hItemNew = pNMTreeView->itemNew.hItem ; if ( hItemNew == nullptr) return ; int nIdNew = int( m_Tree.GetItemData( hItemNew)) ; // ripristino eventuale vecchio oggetto selezionato RevertOldIdInTree() ; // se colore custom if ( ( nIdNew & CMAT) != 0) { OutMaterialData( nIdNew & ~CMAT) ; } // se oggetto geometrico if ( m_pGeomDB->ExistsObj( nIdNew)) { // visualizzo i dati dell'oggetto switch ( m_pGeomDB->GetGdbType( nIdNew)) { case GDB_TY_GROUP : OutGroupData( nIdNew) ; break ; case GDB_TY_GEO : OutGeoObjData( nIdNew) ; break ; } // permetto in ogni caso la visualizzazione dell'oggetto e lo marco int nOldMode = GDB_MD_STD ; m_pGeomDB->GetMode( nIdNew, nOldMode) ; int nMode = (( nOldMode == GDB_MD_HIDDEN) ? GDB_MD_STD : nOldMode) ; m_pGeomDB->SetMode( nIdNew, nMode) ; int nOldStatus = GDB_ST_ON ; m_pGeomDB->GetStatus( nIdNew, nOldStatus) ; int nStat = (( nOldStatus == GDB_ST_OFF) ? GDB_ST_ON : nOldStatus) ; m_pGeomDB->SetStatus( nIdNew, nStat) ; m_pGeomDB->SetMark( nIdNew) ; m_nOldIdTree = nIdNew ; } // aggiorno la visualizzazione m_View.Redraw() ; } //---------------------------------------------------------------------------- void CTestEGrDlg::OnTreeDoubleClick( NMHDR* pNMHDR, LRESULT* pResult) { // assegno il risultato *pResult = 0 ; // recupero l'item su cui è stato eseguito il doppio click CPoint cursorPos ; cursorPos.x = GetCurrentMessage()->pt.x ; cursorPos.y = GetCurrentMessage()->pt.y ; m_Tree.ScreenToClient( &cursorPos) ; HTREEITEM hItem = m_Tree.HitTest( cursorPos) ; if ( hItem == nullptr) return ; // recupero l'Id dell'oggetto associato int nId = int( m_Tree.GetItemData( hItem)) ; if ( ! m_pGeomDB->ExistsObj( nId)) return ; // scrivo la stringa dell'Id nella posizione corrente dell'edit dei comandi m_Cmd.OutputText( ToString( nId)) ; } //---------------------------------------------------------------------------- bool CTestEGrDlg::SelectIdInTree( int nId, HTREEITEM hParent) { HTREEITEM hItem ; if ( hParent == nullptr) hItem = m_Tree.GetRootItem() ; else hItem = m_Tree.GetChildItem( hParent) ; while ( hItem != nullptr) { // verifico se ha l'Id cercato int nData = int( m_Tree.GetItemData( hItem)) ; if ( nId == nData) { m_Tree.SelectItem( hItem) ; return true ; } // se ci sono dei figli, li analizzo if ( m_Tree.ItemHasChildren( hItem)) { if ( SelectIdInTree( nId, hItem)) return true ; } // passo al successivo fratello hItem = m_Tree.GetNextSiblingItem( hItem) ; } return false ; } //---------------------------------------------------------------------------- int CTestEGrDlg::RevertOldIdInTree( void) { // verifiche sul DB geometrico if ( m_pGeomDB == nullptr) return GDB_ID_NULL ; // salvo il vecchio Id int nOldId = m_nOldIdTree ; // se non nullo... if ( m_pGeomDB->ExistsObj( m_nOldIdTree)) { // ripristino il modo e lo stato precedente dell'oggetto e lo smarco m_pGeomDB->RevertMode( m_nOldIdTree) ; m_pGeomDB->RevertStatus( m_nOldIdTree) ; m_pGeomDB->ResetMark( m_nOldIdTree) ; // annullo oggetto da ripristinare m_nOldIdTree = GDB_ID_NULL ; } return nOldId ; } //---------------------------------------------------------------------------- void CTestEGrDlg::OutMaterialData( int nId) { string sName ; Material matM ; if ( m_pGeomDB->GetMaterialName( nId, sName) && m_pGeomDB->GetMaterialData( nId, matM)) { string sOut = "Custom material " + sName + "\r\n" ; sOut += " AmbCol = " + ToString( matM.GetAmbient()) + "\r\n" ; sOut += " DiffCol = " + ToString( matM.GetDiffuse()) + "\r\n" ; sOut += " SpecCol = " + ToString( matM.GetSpecular()) + "\r\n" ; sOut += " Shininess = " + ToString( matM.GetShininess()) + "\r\n" ; OutData( sOut) ; } else OutData( "") ; } //---------------------------------------------------------------------------- void CTestEGrDlg::OutGroupData( int nId) { // preparo l'intestazione string sOut = "Group " + ToString( nId) + "\r\n" ; // preparo gli attributi m_pGeomDB->DumpAttributes( nId, sOut, "\r\n") ; // numero di nodi (figli) int nNodes = m_pGeomDB->GetGroupObjs( nId) ; sOut += "Nodes : " + ToString( nNodes) + "\r\n" ; // riferimento in globale Frame3d frGlob ; if ( m_pGeomDB->GetGroupGlobFrame( nId, frGlob)) { sOut += "GlobFrame :\r\n" ; sOut += " O(" + ToString( frGlob.Orig()) + ")\r\n" ; sOut += " X(" + ToString( frGlob.VersX()) + ")\r\n" ; sOut += " Y(" + ToString( frGlob.VersY()) + ")\r\n" ; sOut += " Z(" + ToString( frGlob.VersZ()) + ")\r\n" ; } // ingombro in globale BBox3d b3Glob ; if ( m_pGeomDB->GetGlobalBBox( nId, b3Glob)) { sOut += "GlobBBox :\r\n" ; Point3d ptMin, ptMax ; if ( b3Glob.GetMinMax( ptMin, ptMax)) { sOut += " m(" + ToString( ptMin) + ")\r\n" ; sOut += " M(" + ToString( ptMax) + ")\r\n" ; } else { sOut += " Empty\r\n" ; } } OutData( sOut) ; } //---------------------------------------------------------------------------- void CTestEGrDlg::OutGeoObjData( int nId) { // recupero l'oggetto geometrico const IGeoObj* pGObj ; if ( ( pGObj = m_pGeomDB->GetGeoObj( nId)) == nullptr) return ; // preparo l'intestazione string sOut = pGObj->GetTitle() + " " + ToString( nId) + "\r\n" ; // preparo gli attributi m_pGeomDB->DumpAttributes( nId, sOut, "\r\n") ; // preparo i dati geometrici pGObj->Dump( sOut, "\r\n") ; // emissione OutData( sOut) ; }