GME  13
AggregateTreeCtrl.cpp
Go to the documentation of this file.
00001 // AggregateTreeCtrl.cpp: implementation of the CAggregateTreeCtrl class.
00002 //
00004 
00005 #include "stdafx.h"
00006 #include "gmeactivebrowser.h"
00007 #include "AggregateTreeCtrl.h"
00008 #include "ActiveBrowserPropertyPage.h"
00009 #include "..\gme\GMEOLEData.h"
00010 
00011 #include <GdiPlus.h>
00012 #pragma comment(lib, "gdiplus.lib")
00013 #include "..\..\SDK\DecoratorLib\PathUtil.h"
00014 
00015 #ifdef _DEBUG
00016 #undef THIS_FILE
00017 static char THIS_FILE[]=__FILE__;
00018 #define new DEBUG_NEW
00019 #endif
00020 
00021 
00023 // Construction/Destruction
00025 
00026 CAggregateTreeCtrl::CAggregateTreeCtrl()
00027 {
00028 
00029         m_bIsStateStored=FALSE;
00030 
00031 }
00032 
00033 CAggregateTreeCtrl::~CAggregateTreeCtrl()
00034 {
00035 
00036 }
00037 
00038 HTREEITEM CAggregateTreeCtrl::InsertItem(HTREEITEM hParent, CString strObjectName, LPUNKNOWN pUnknown, objtype_enum otObjectType, bool update)
00039 {
00040         if (update)
00041         {
00042                 MGATREECTRL_LOGEVENT("CAggregateTreeCtrl::InsertItemUpdate "+strObjectName+"\r\n");
00043 
00044                 HTREEITEM hTreeItem;
00045                 if(m_MgaMap.LookupTreeItem(pUnknown,hTreeItem))
00046                 {
00047                         return hTreeItem;
00048                 }
00049         }
00050         else
00051         {
00052                 MGATREECTRL_LOGEVENT("CAggregateTreeCtrl::InsertItem "+strObjectName+"\r\n");
00053 
00054                 if (m_MgaMap.bIsInMap(pUnknown)) // Should not happen
00055                 {
00056                         TRACE(" Duplicate element found inserting a new element into the aggregation tree map.\n");
00057 #ifdef _DEBUG
00058                         m_MgaMap.Dump(afxDump);
00059                         ASSERT(FALSE);
00060 #endif
00061 
00062                         return NULL;
00063                 }
00064         }
00065 
00066 
00067         TVINSERTSTRUCT tvInsert;
00068         tvInsert.hParent = hParent;
00069         tvInsert.hInsertAfter = NULL; // FIXME: does this mean we're doing insertion sort?
00070         tvInsert.item.pszText = strObjectName.GetBuffer(0);
00071 
00072         tvInsert.item.state=0;
00073         tvInsert.item.stateMask=0;
00074         tvInsert.item.lParam=NULL;
00075 
00076         CAggregatePropertyPage* pParent=(CAggregatePropertyPage*)GetParent();
00077 
00078         int sourceControlImageOffset = 0;
00079         int sourceControlLatentState = 0;
00080 
00081         if(pParent->m_Options.m_bIsDynamicLoading)
00082         {
00083                 tvInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE|TVIF_CHILDREN;
00084                 if(otObjectType==OBJTYPE_FOLDER || otObjectType==OBJTYPE_MODEL)
00085                 {
00086                         CComQIPtr<IMgaObject> ccpMgaObject(pUnknown);
00087                         tvInsert.item.cChildren=pParent->reqHasDisplayedChild(ccpMgaObject);
00088                         //sourceControlImageOffset = pParent->GetSourceControlStateOffset(ccpMgaObject, &sourceControlLatentState);
00089                 }
00090                 else
00091                 {
00092                         tvInsert.item.cChildren=0;
00093                 }
00094                 sourceControlImageOffset = pParent->GetSourceControlStateOffset(CComQIPtr<IMgaObject>( pUnknown), &sourceControlLatentState);
00095         }
00096         else
00097         {
00098                 tvInsert.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
00099         }
00100 
00101         if(hParent==NULL)       // Root folder
00102         {
00103 
00104                 tvInsert.item.iImage=0+sourceControlImageOffset;
00105                 tvInsert.item.iSelectedImage=0+sourceControlImageOffset;
00106         }
00107         else
00108         {
00109                 tvInsert.item.iImage=(int)otObjectType+sourceControlImageOffset;
00110                 tvInsert.item.iSelectedImage=(int)otObjectType+sourceControlImageOffset;
00111         }
00112 
00113         if(otObjectType==OBJTYPE_FOLDER)
00114         {
00115                 bool has_dep;
00116                 if(IsLibrary(pUnknown, &has_dep))
00117                 {
00118                         tvInsert.item.iImage=10 + sourceControlImageOffset;
00119                         tvInsert.item.iSelectedImage=10 + sourceControlImageOffset;
00120                         if( has_dep)
00121                         {
00122                                 tvInsert.item.iImage=54;
00123                                 tvInsert.item.iSelectedImage=54;
00124                         }
00125                 }
00126                         
00127 
00128         }
00129 
00130         CComPtr<IMgaObject> ccpObject;
00131         QueryInterface(pUnknown, &ccpObject);
00132         GetCustomTreeIcon(ccpObject, tvInsert.item);
00133 
00134         // Inserting item into the tree control
00135         HTREEITEM hItem = CTreeCtrl::InsertItem(&tvInsert);
00136         strObjectName.ReleaseBuffer();
00137 
00138         // tvInsert.item.iImage = 0;
00139         SetItemData(hItem,(DWORD)hItem);
00140         
00141         CAggregateMgaObjectProxy ObjectProxy(pUnknown, otObjectType);
00142         CAggregateMgaObjectProxy& insertedProxy = m_MgaMap.AddEntry(hItem, ObjectProxy);
00143 
00144         SetItemProperties(hItem, sourceControlLatentState, &insertedProxy);
00145         
00146         return hItem;
00147 
00148 }
00149 
00150 
00151 HTREEITEM CAggregateTreeCtrl::InsertItemUpdate(HTREEITEM hParent, CString strObjectName, LPUNKNOWN pUnknown, objtype_enum otObjectType)
00152 {
00153         return InsertItem(hParent, strObjectName, pUnknown, otObjectType, true);
00154 }
00155 
00156 
00157 void CAggregateTreeCtrl::MaintainRegistry()
00158 {
00159         BYTE nMaxStored=4;
00160 
00161         HKEY hKey;                  // handle to key to enumerate
00162         DWORD dwIndex=0;            // subkey index
00163         TCHAR szName[255];           // subkey name
00164         DWORD lName=254;                                // size of subkey buffer
00165         TCHAR szClass[255];          // class string buffer
00166         DWORD lClass=254;                               // size of class string buffer
00167         FILETIME ftLastWriteTime;       // last write time
00168         
00169         FILETIME ftOldestWriteTime;     // oldest write time
00170         CString strOldestName;          // Name of the oldest key
00171 
00172 
00173         // Initializing filetime with the current system time    
00174     SYSTEMTIME stSystemTime;    
00175     GetSystemTime(&stSystemTime);              // gets current time
00176          // converts to file time format
00177     SystemTimeToFileTime(&stSystemTime, &ftOldestWriteTime); 
00178 
00179         // Getting the key of Tree Data
00180         hKey=AfxGetApp()->GetSectionKey(_T("TreeData"));
00181 
00182         for(dwIndex=0;
00183                 ERROR_NO_MORE_ITEMS!=
00184                 RegEnumKeyEx(hKey,dwIndex,szName,&lName,NULL,szClass,&lClass,&ftLastWriteTime);
00185                 dwIndex++,lName=254,lClass=254
00186                 )
00187         {
00188                         // If the current is earlier
00189                         if(::CompareFileTime(&ftLastWriteTime,&ftOldestWriteTime)==-1)
00190                         {
00191                                 ftOldestWriteTime=ftLastWriteTime;
00192                                 strOldestName=szName;
00193                         }
00194         }
00195 
00196         if(dwIndex>nMaxStored)
00197         {
00198                 // Deleting the oldest key                      
00199                 ::RegDeleteKey(HKEY_CURRENT_USER,CString("Software\\")+
00200                                                                                                         AfxGetApp()->m_pszRegistryKey+
00201                                                                                                         AfxGetApp()->m_pszProfileName+
00202                                                                                                         "\\TreeData\\"+strOldestName);
00203         }
00204         
00205         ::RegCloseKey(hKey);
00206 }
00207 
00208 
00209 void CAggregateTreeCtrl::LoadItemStateFromRegistry(CString& strProjectName, HTREEITEM hItem)
00210 {               
00211 
00212                 // Searching hte map for the Mga pointer
00213                 LPUNKNOWN pUnknown;
00214                 if(m_MgaMap.LookupObjectUnknown(hItem,pUnknown))
00215                 {
00216                         CComQIPtr<IMgaObject>ccpMgaObject(pUnknown);
00217                         if(ccpMgaObject) // succesful conversion
00218                         {
00219                                 CComBSTR IDObj;
00220                                 COMTHROW(ccpMgaObject->get_ID(&IDObj));
00221 
00222                                 // Get Object id and item state in the registry
00223                                 CString strID(IDObj);                           
00224                                 UINT nItemState=AfxGetApp()->GetProfileInt(CString("TreeData\\")+strProjectName,strID,0xffffffff);
00225 
00226                 
00227                                 if(nItemState!=0xffffffff)
00228                                 {
00229                                         __super::SetItemState(hItem,nItemState);
00230                                 }
00231 
00232                         }
00233                 }
00234 }
00235 
00236 
00237 void CAggregateTreeCtrl::LoadTreeStateFromRegistry(CString& strProjectName)
00238 {
00239 
00240         // If the key does not exist return
00241         HKEY hKey;
00242         if(ERROR_SUCCESS!=::RegOpenKeyEx(HKEY_CURRENT_USER,
00243                 CString("Software\\")+
00244                 AfxGetApp()->m_pszRegistryKey+
00245                 "\\" +
00246                 AfxGetApp()->m_pszProfileName+
00247                 "\\TreeData\\"+
00248                 strProjectName,
00249                 0,KEY_ALL_ACCESS,&hKey))
00250         {
00251                 return;
00252         }
00253         else
00254         {
00255                 ::RegCloseKey(hKey);
00256         }
00257         
00258         
00259         
00260         // Traverse all items in tree control
00261         HTREEITEM hItem= GetRootItem();
00262 
00263         while ( hItem )
00264         {
00265                 /* Getting the items to the registry            */
00266                 LoadItemStateFromRegistry(strProjectName,hItem);
00267                 
00268                 // Get first child node
00269                 HTREEITEM hNextItem = GetChildItem( hItem );
00270 
00271                 if ( !hNextItem )
00272                 {
00273                         // Get next sibling child
00274                         hNextItem = GetNextSiblingItem( hItem );
00275 
00276                         if ( !hNextItem )
00277                         {
00278                                 HTREEITEM hParentItem=hItem;
00279                                 while ( !hNextItem && hParentItem )
00280                                 {
00281                                         // No more children: Get next sibling to parent
00282                                         hParentItem = GetParentItem( hParentItem );
00283                                         hNextItem = GetNextSiblingItem( hParentItem );
00284                                 }
00285                         }
00286                 }
00287 
00288                 hItem = hNextItem;
00289         }
00290 
00291         // Deleting the key                     
00292         ::RegDeleteKey(HKEY_CURRENT_USER,CString("Software\\")+AfxGetApp()->m_pszRegistryKey+AfxGetApp()->m_pszProfileName+
00293                                                                                                         "\\TreeData\\"+strProjectName);
00294 
00295         return;
00296 
00297 }
00298 
00299 
00300 
00301 void CAggregateTreeCtrl::SaveTreeStateToRegistry(CString& strProjectName)
00302 {
00303         // Traverse all items in tree control
00304         HTREEITEM hItem= GetRootItem();
00305 
00306         while ( hItem )
00307         {
00308                 /* Saving the items to the registry             */
00309                 // Getting item state
00310                 UINT nItemState=CTreeCtrlEx::GetItemState(hItem,0xffffffff);
00311                 nItemState = nItemState & ~TVIS_BOLD;
00312 
00313                 // Searching the map for the Mga pointer
00314                 LPUNKNOWN pUnknown;
00315                 if(m_MgaMap.LookupObjectUnknown(hItem,pUnknown))
00316                 {
00317                         CComQIPtr<IMgaObject>ccpMgaObject(pUnknown);
00318                         if(ccpMgaObject) // succesful conversion
00319                         {
00320                                 CComBSTR IDObj;
00321                                 COMTHROW(ccpMgaObject->get_ID(&IDObj));
00322 
00323                                 // Put Object id and item state in the registry
00324                                 CString strID(IDObj);
00325                                 
00326                                 AfxGetApp()->WriteProfileInt(CString("TreeData\\")+strProjectName,strID,nItemState);
00327                         }
00328                 }
00329 
00330                 // Get first child node
00331                 HTREEITEM hNextItem = GetChildItem( hItem );
00332 
00333                 if ( !hNextItem )
00334                 {
00335                         // Get next sibling child
00336                         hNextItem = GetNextSiblingItem( hItem );
00337 
00338                         if ( !hNextItem )
00339                         {
00340                                 HTREEITEM hParentItem=hItem;
00341                                 while ( !hNextItem && hParentItem )
00342                                 {
00343                                         // No more children: Get next sibling to parent
00344                                         hParentItem = GetParentItem( hParentItem );
00345                                         hNextItem = GetNextSiblingItem( hParentItem );
00346                                 }
00347                         }
00348                 }
00349 
00350                 hItem = hNextItem;
00351         }
00352 
00353         // If there is too many project trees stored in the registry 
00354         // we delete the oldest one
00355         MaintainRegistry();
00356         return;
00357 
00358 }
00359 
00360 
00361 void CAggregateTreeCtrl::StoreState()
00362 {
00363 
00364         m_StateBuffer.RemoveAll();
00365 
00366         // Traverse all items in tree control
00367         HTREEITEM hItem= GetRootItem();
00368 
00369         while ( hItem )
00370         {
00371                 /* Saving the items to the state buffer         */
00372                 // Getting item state
00373                 UINT nItemState=CTreeCtrlEx::GetItemState(hItem,0x000000ff);
00374                 CString strItemState;
00375                 strItemState.Format(_T("%ul"),nItemState);
00376 
00377                 // Searching the map for the Mga pointer
00378                 LPUNKNOWN pUnknown;
00379                 if(m_MgaMap.LookupObjectUnknown(hItem,pUnknown))
00380                 {
00381                         CComQIPtr<IMgaObject>ccpMgaObject(pUnknown);
00382                         if(ccpMgaObject) // succesful conversion
00383                         {
00384                                 CComBSTR IDObj;
00385                                 COMTHROW(ccpMgaObject->get_ID(&IDObj));
00386 
00387                                 // Put Object id and item state in the buffer
00388                                 CString strID(IDObj);
00389                                 m_StateBuffer.SetAt(strID,strItemState);
00390                                 
00391                         }
00392                 }
00393 
00394                 // Get first child node
00395                 HTREEITEM hNextItem = GetChildItem( hItem );
00396 
00397                 if ( !hNextItem )
00398                 {
00399                         // Get next sibling child
00400                         hNextItem = GetNextSiblingItem( hItem );
00401 
00402                         if ( !hNextItem )
00403                         {
00404                                 HTREEITEM hParentItem=hItem;
00405                                 while ( !hNextItem && hParentItem )
00406                                 {
00407                                         // No more children: Get next sibling to parent
00408                                         hParentItem = GetParentItem( hParentItem );
00409                                         hNextItem = GetNextSiblingItem( hParentItem );
00410                                 }
00411                         }
00412                 }
00413 
00414                 hItem = hNextItem;
00415         }
00416 
00417         m_bIsStateStored=TRUE;
00418         return;
00419 
00420 }
00421 
00422 
00423 
00424 void CAggregateTreeCtrl::RestoreState()
00425 {
00426         if(!m_bIsStateStored)return;
00427 
00428         // Traverse all items in tree control
00429         HTREEITEM hItem= GetRootItem();
00430 
00431         while ( hItem )
00432         {
00433                 /* Getting the item from the map                */
00434                 
00435                 // Searching the map for the Mga pointer
00436                 LPUNKNOWN pUnknown;
00437                 if(m_MgaMap.LookupObjectUnknown(hItem,pUnknown))
00438                 {
00439                         CComQIPtr<IMgaObject>ccpMgaObject(pUnknown);
00440                         if(ccpMgaObject) // succesful conversion
00441                         {
00442                                 CComBSTR IDObj;
00443                                 COMTHROW(ccpMgaObject->get_ID(&IDObj));
00444 
00445                                 // Get Object id and item state from the map
00446                                 CString strID(IDObj);
00447                                 CString strItemState;
00448                                 if(m_StateBuffer.Lookup(strID,strItemState))
00449                                 {
00450                                         TCHAR* pszEndPtr=NULL;
00451                                         UINT nItemState=_tcstoul(strItemState,&pszEndPtr,10);                                                                                                           
00452                                         __super::SetItemState(hItem,nItemState);
00453                                 }
00454                         }
00455                 }
00456                 
00457                 // Get first child node
00458                 HTREEITEM hNextItem = GetChildItem( hItem );
00459 
00460                 if ( !hNextItem )
00461                 {
00462                         // Get next sibling child
00463                         hNextItem = GetNextSiblingItem( hItem );
00464 
00465                         if ( !hNextItem )
00466                         {
00467                                 HTREEITEM hParentItem=hItem;
00468                                 while ( !hNextItem && hParentItem )
00469                                 {
00470                                         // No more children: Get next sibling to parent
00471                                         hParentItem = GetParentItem( hParentItem );
00472                                         hNextItem = GetNextSiblingItem( hParentItem );
00473                                 }
00474                         }
00475                 }
00476 
00477                 hItem = hNextItem;
00478         }
00479 
00480         m_StateBuffer.RemoveAll();
00481         m_bIsStateStored=FALSE;
00482         return;
00483 }
00484 
00485 
00486 
00487 
00488 
00489 int CAggregateTreeCtrl::ItemCompareProc(LPARAM lParamItem1, LPARAM lParamItem2, LPARAM lParamSort)
00490 {
00491 
00492 
00493         CAggregateTreeCtrl* pTreeCtrl = (CAggregateTreeCtrl*) lParamSort;
00494 
00495         HTREEITEM hItem1=(HTREEITEM) lParamItem1;
00496         HTREEITEM hItem2=(HTREEITEM) lParamItem2;
00497 
00498         
00499         CAggregatePropertyPage* pParent=(CAggregatePropertyPage*)pTreeCtrl->GetParent();
00500 
00501         switch(pParent->m_Options.m_soSortOptions)
00502         {               
00503                 case SORT_BYNAME:
00504                         {
00505                                 CString strItem1 = pTreeCtrl->GetItemText(hItem1);
00506                                 CString strItem2 = pTreeCtrl->GetItemText(hItem2);
00507                                 return -_tcscmp(strItem2, strItem1);
00508                         }break;
00509                 case SORT_BYTYPE:
00510                         {
00511                                 CAggregateMgaObjectProxy MgaObjectProxyItem1;
00512                                 CAggregateMgaObjectProxy MgaObjectProxyItem2;
00513                                 if(
00514                                         pTreeCtrl->m_MgaMap.LookupObjectProxy(hItem1,MgaObjectProxyItem1) &&
00515                                         pTreeCtrl->m_MgaMap.LookupObjectProxy(hItem2,MgaObjectProxyItem2))
00516                                 {
00517                                         // Same Type - Sort By Name
00518                                         if(MgaObjectProxyItem1.m_TypeInfo==MgaObjectProxyItem2.m_TypeInfo)
00519                                         {
00520                                                 CString strItem1 = pTreeCtrl->GetItemText(hItem1);
00521                                                 CString strItem2 = pTreeCtrl->GetItemText(hItem2);
00522                                                 return -_tcscmp(strItem2, strItem1);
00523 
00524                                         }
00525 
00526                                         // Folder has a high priority
00527                                         if(MgaObjectProxyItem1.m_TypeInfo==OBJTYPE_FOLDER)
00528                                         {
00529                                                 return -1;
00530                                         }
00531 
00532                                         if(MgaObjectProxyItem2.m_TypeInfo==OBJTYPE_FOLDER)
00533                                         {
00534                                                 return 1;
00535                                         }
00536 
00537                                         return MgaObjectProxyItem1.m_TypeInfo-MgaObjectProxyItem2.m_TypeInfo;
00538                                 }
00539                                 else
00540                                 {
00541                                         // For dummy elements that are not in the map it does not matter
00542                                         return 0;
00543                                 }
00544 
00545                         }break;
00546                 case SORT_BYCREATION:
00547                         {
00548                                 
00549                                 CAggregateMgaObjectProxy MgaObjectProxyItem1;
00550                                 CAggregateMgaObjectProxy MgaObjectProxyItem2;
00551 
00552                                 if(
00553                                         pTreeCtrl->m_MgaMap.LookupObjectProxy(hItem1,MgaObjectProxyItem1) &&
00554                                         pTreeCtrl->m_MgaMap.LookupObjectProxy(hItem2,MgaObjectProxyItem2))
00555                                 {
00556                                         CComQIPtr<IMgaObject>ccpItem1(MgaObjectProxyItem1.m_pMgaObject);
00557                                         CComQIPtr<IMgaObject>ccpItem2(MgaObjectProxyItem2.m_pMgaObject);
00558 
00559                                         if(ccpItem1 &&ccpItem2)
00560                                         {                                               
00561                                                 // Query the RelativeID
00562                                                 long lRelID1,lRelID2;
00563                                                 COMTHROW(ccpItem1->get_RelID(&lRelID1));
00564                                                 COMTHROW(ccpItem2->get_RelID(&lRelID2));                                                                                                                                        
00565                                                 
00566                                                 return lRelID1-lRelID2;
00567                                         }
00568                                         else // Unsuccessful query of the objects
00569                                         {
00570                                                 return 0;
00571                                         }
00572 
00573                                 }
00574                                 else
00575                                 {
00576                                         // For dummy elements that are not in the map it does not matter
00577                                         return 0;
00578                                 }
00579 
00580                         }break;
00581         }
00582         return 0;
00583 }
00584 
00585 void CAggregateTreeCtrl::SortItems(HTREEITEM hItem)
00586 {
00587         // Sort the tree control's items using 
00588         // custom callback procedure.
00589 
00590                 // Traverse all items in tree control
00591 
00592         if(hItem==NULL)
00593         {
00594                 hItem= GetRootItem();
00595         }
00596 
00597         while ( hItem )
00598         {
00599                         TVSORTCB tvs;
00600                         tvs.hParent = hItem;
00601                         tvs.lpfnCompare = (PFNTVCOMPARE)ItemCompareProc;
00602                         tvs.lParam = (LPARAM) this;
00603 
00604                         CTreeCtrl::SortChildrenCB(&tvs);
00605                 
00606 
00607                 // Get first child node
00608                 HTREEITEM hNextItem = GetChildItem( hItem );
00609 
00610                 if ( !hNextItem )
00611                 {
00612                         // Get next sibling child
00613                         hNextItem = GetNextSiblingItem( hItem );
00614 
00615                         if ( !hNextItem )
00616                         {
00617                                 HTREEITEM hParentItem=hItem;
00618                                 while ( !hNextItem && hParentItem )
00619                                 {
00620                                         // No more children: Get next sibling to parent
00621                                         hParentItem = GetParentItem( hParentItem );
00622                                         hNextItem = GetNextSiblingItem( hParentItem );
00623                                 }
00624                         }
00625                 }
00626 
00627                 hItem = hNextItem;
00628         }
00629 
00630 }
00631 
00632 
00633 void CAggregateTreeCtrl::MakeSureGUIDIsUniqueForSmartCopy( CComPtr<IMgaFCO>& fco)
00634 {
00635         // this method prevents cloned objects having the same guid
00636         // as their original ones
00637         CComBSTR bstr;
00638         COMTHROW( fco->get_RegistryValue( CComBSTR( "guid"), &bstr));
00639         if( bstr == 0 || bstr == "") return; // no guid present, no need to replace it
00640 
00641         GUID t_guid = GUID_NULL;
00642         ::CoCreateGuid(&t_guid);
00643                 
00644         if (t_guid != GUID_NULL)
00645         {
00646                 CString str_guid;
00647                 str_guid.Format(_T("{%08lX-%04X-%04x-%02X%02X-%02X%02X%02X%02X%02X%02X}"),
00648                         t_guid.Data1, t_guid.Data2, t_guid.Data3,
00649                         t_guid.Data4[0], t_guid.Data4[1], t_guid.Data4[2], t_guid.Data4[3],
00650                         t_guid.Data4[4], t_guid.Data4[5], t_guid.Data4[6], t_guid.Data4[7]);
00651                 
00652                 // thus replace the old guid with a new one
00653                 COMTHROW( fco->put_RegistryValue( CComBSTR( "guid"), CComBSTR(str_guid)));
00654         }
00655 
00656         // store the previous guid in prev subnode
00657         COMTHROW( fco->put_RegistryValue( CComBSTR( "guid/prev"), bstr));
00658 }
00659 
00660 
00661 
00662 BOOL CAggregateTreeCtrl::IsRelevantDropTarget(CPoint point,CImageList* pDragImageList)
00663 {
00664         UINT uFlags;
00665         HTREEITEM hItem = HitTest(point, &uFlags);
00666         
00667         if ((hItem != NULL) && (TVHT_ONITEM & uFlags))
00668         {
00669                 CAggregateMgaObjectProxy ObjectProxy;
00670                 if(m_MgaMap.LookupObjectProxy(hItem,ObjectProxy)) // If it is in the map
00671                 {
00672                         if(ObjectProxy.m_TypeInfo==OBJTYPE_FOLDER || ObjectProxy.m_TypeInfo==OBJTYPE_MODEL)
00673                         {
00674                                 return TRUE;
00675                         }
00676                 }               
00677         }
00678         return FALSE;
00679 }
00680 
00681 BOOL CAggregateTreeCtrl::DoDrop(eDragOperation doDragOp, COleDataObject *pDataObject, CPoint point)
00682 {
00683         MGATREECTRL_LOGEVENT("CAggregateTreeCtrl::DoDrop\r\n");
00684         CString _t = "";
00685         if( doDragOp == DRAGOP_REFERENCE)
00686                 _t = " REFERENCE\r\n";
00687         if( doDragOp == DRAGOP_SUBTYPE)
00688                 _t = " DERIVE\r\n";
00689         if( doDragOp == DRAGOP_INSTANCE)
00690                 _t = " INSTANCE\r\n";
00691         if( doDragOp == DRAGOP_COPY)
00692                 _t = " COPY\r\n";
00693         if( doDragOp == DRAGOP_MOVE)
00694                 _t = " MOVE\r\n";
00695         if( doDragOp == DRAGOP_CLOSURE)
00696                 _t = " CLOSURE COPY\r\n";
00697         if( doDragOp == DRAGOP_CLOSURE_MERGE)
00698                 _t = " COPY MERGE\r\n";
00699         MGATREECTRL_LOGEVENT( _t);
00700 
00701         HTREEITEM hItem;
00702         if (point.x == 0 && point.y == 0) {
00703                 hItem = GetSelectedItem();
00704         } else {
00705                 hItem = HitTest(point);
00706         }
00707         
00708         CAggregateMgaObjectProxy MgaObjectProxy;
00709 
00710         if(hItem==NULL || !m_MgaMap.LookupObjectProxy(hItem,MgaObjectProxy))
00711         {
00712                 ASSERT(FALSE);
00713                 return FALSE;
00714         }
00715 
00716         
00717         CGMEActiveBrowserApp* pApp=(CGMEActiveBrowserApp*)AfxGetApp();
00718         CMgaContext* pMgaContext=&pApp->m_CurrentProject.m_MgaContext;
00719         
00720         // Setting up the drop target 
00721         CComQIPtr<IMgaObject> ccpTargetObject(MgaObjectProxy.m_pMgaObject);
00722         if(!ccpTargetObject) 
00723         {
00724                 MessageBox(_T("Invalid target type."),_T("Error"),MB_OK|MB_ICONERROR);
00725                 return FALSE;
00726         }
00727 
00728         // PETER: Checking clipboard, paste XML clipboard.
00729         if (!CGMEDataSource::IsGmeNativeDataAvailable(pDataObject,pMgaContext->m_ccpProject)) 
00730         {
00731                 if (!CGMEDataSource::IsXMLDataAvailable(pDataObject))  {
00732                         MessageBox(_T("Unknown clipboard format."),_T("Error"),MB_OK|MB_ICONERROR);
00733                         return FALSE;
00734                 }
00735                 if (doDragOp != DRAGOP_COPY && doDragOp != DRAGOP_CLOSURE && doDragOp != DRAGOP_CLOSURE_MERGE) {
00736                         MessageBox(_T("Only copy operation is supported on GME XML clipboard format."),_T("Error"),MB_OK|MB_ICONERROR);
00737                         return FALSE;
00738                 }
00739                         
00740                 try {
00741                         bool res = CGMEDataSource::ParseXMLData(pDataObject, ccpTargetObject, doDragOp == DRAGOP_CLOSURE_MERGE);
00742                         return res?TRUE:FALSE;
00743                 } catch (hresult_exception& e) {
00744                         return FALSE;
00745                 }
00746         }
00747         // PETER: end
00748         
00749 
00750         CComPtr<IDataObject> ccpDataObject = pDataObject->GetIDataObject(FALSE);
00751         CComPtr<IMgaDataSource> ccpMgaDataSource;
00752         COMTHROW(ccpDataObject.QueryInterface(&ccpMgaDataSource));
00753 
00754         CComPtr<IUnknown> ccpData;
00755         COMTHROW(ccpMgaDataSource->get_Data( &ccpData));
00756         
00757         CComPtr<IUnknown> ccpFolders;
00758         COMTHROW(ccpMgaDataSource->get_Folders( &ccpFolders));
00759         
00760         CComPtr<IMgaResolver> ccpMgaResolver;
00761         COMTHROW( ccpMgaResolver.CoCreateInstance(L"Mga.MgaResolver") );
00762 
00763         CComQIPtr<IMgaFCOs> ccpDroppedFCOs( ccpData);
00764         CComQIPtr<IMgaFolders> ccpDroppedFolders( ccpFolders);
00765 
00766         if (!ccpDroppedFCOs && !ccpDroppedFolders) {
00767                 BOOL bRetVal = FALSE;
00768 
00769                 MSGTRY {
00770                         CComQIPtr<IMgaMetaRole> metaRole(ccpData);
00771                         if (metaRole) {
00772                                 CComPtr<IMgaFCO> child;
00773                                 pMgaContext->BeginTransaction(FALSE); // Read/Write Transaction
00774                                 if (MgaObjectProxy.m_TypeInfo == OBJTYPE_MODEL) {       // If the drop target is a model
00775                                         CComQIPtr<IMgaModel> ccpTargetModel(MgaObjectProxy.m_pMgaObject);
00776                                         switch (doDragOp) {
00777                                                 case DRAGOP_MOVE:
00778                                                 case DRAGOP_COPY:
00779                                                 {
00780                                                         COMTHROW(ccpTargetModel->CreateChildObject(metaRole, &child));
00781                                                 } break;                                
00782                                         }       // switch
00783                                 } else if (MgaObjectProxy.m_TypeInfo == OBJTYPE_FOLDER) { // If the drop target is a folder
00784                                         CComQIPtr<IMgaFolder> ccpTargetFolder(MgaObjectProxy.m_pMgaObject);
00785                                         switch (doDragOp) {
00786                                                 case DRAGOP_MOVE:
00787                                                 case DRAGOP_COPY:
00788                                                 {
00789                                                         CComPtr<IMgaMetaFCO> metaFCO;
00790                                                         COMTHROW(metaRole->get_Kind(&metaFCO));
00791                                                         if (metaFCO)
00792                                                                 COMTHROW(ccpTargetFolder->CreateRootObject(metaFCO, &child));
00793                                                 } break;                                
00794                                         }       // switch
00795                                 }
00796                                 if (child) {
00797                                         CComBSTR nm;
00798                                         COMTHROW(metaRole->get_DisplayedName(&nm));
00799                                         COMTHROW(child->put_Name(nm));
00800                                 }
00801                                 pMgaContext->CommitTransaction ();
00802                         }
00803                 } MSGCATCH (_T("Error completing PartBrowser drop operation"), pMgaContext->AbortTransaction ();)       
00804 
00805                 return bRetVal;
00806         }
00807 
00808         // ccpDroppedFCOs can't be null since every copier creates the Mga.MgaFCOs collection even if no element is added
00809         // ccpDroppedFolders might be null i.e. GMEDoc does not create the Mga.MgaFolders collection
00810         // when an fco is dragged from the GMEView to the ActiveBrowser
00811 
00812         BOOL bRetVal=FALSE;
00813 
00814         MSGTRY{
00815                 pMgaContext->BeginTransaction(TRANSACTION_NON_NESTED); // Read/Write Transaction
00816                 if(MgaObjectProxy.m_TypeInfo==OBJTYPE_FOLDER) // If the drop target is a folder
00817                 {
00818                         CComQIPtr<IMgaFolder> ccpTargetFolder(MgaObjectProxy.m_pMgaObject);
00819 
00820                         switch(doDragOp)
00821                         {
00822                                 case DRAGOP_MOVE:
00823                                 {
00824                                         CComPtr<IMgaFolders> ccpNewFolders;
00825                                         CComPtr<IMgaFCOs> ccpNewFCOs;
00826 
00827                                         // first move the selected folders. The order matters 
00828                                         // since the NEWCHILD event must be the last one.
00829                                         if (ccpDroppedFolders)
00830                                                 ccpTargetFolder->__MoveFolders(ccpDroppedFolders, &ccpNewFolders);
00831 
00832                                         // then move the selected fcos
00833                                         ccpTargetFolder->__MoveFCOs(ccpDroppedFCOs, &ccpNewFCOs);
00834 
00835                                         // this ensures that the new parent is notified in the right time and place
00836                                         // a NEWCHILD event is sent to the target folder
00837                                         COMTHROW( ccpTargetFolder->RefreshParent( ccpTargetFolder));
00838 
00839                                         bRetVal=TRUE;
00840                                 }break;
00841                                 case DRAGOP_COPY:
00842                                 {
00843                                         CComPtr<IMgaFolders> ccpNewFolders;
00844                                         if (ccpDroppedFolders)
00845                                                 ccpTargetFolder->__CopyFolders(ccpDroppedFolders,&ccpNewFolders);
00846 
00847                                         CComPtr<IMgaFCOs> ccpNewFCOs;
00848                                         ccpTargetFolder->__CopyFCOs(ccpDroppedFCOs,&ccpNewFCOs);
00849                                         
00850                                         MGACOLL_ITERATE(IMgaFCO, ccpNewFCOs) { // for smart copy related entries
00851                                                 MakeSureGUIDIsUniqueForSmartCopy( CComPtr<IMgaFCO>( MGACOLL_ITER) );
00852                                         } MGACOLL_ITERATE_END;
00853 
00854                                         bRetVal=TRUE;
00855                                 }break;
00856                                 case DRAGOP_REFERENCE:
00857                                 {
00859                                         bRetVal=FALSE;
00860                                 }break;
00861                                 case DRAGOP_INSTANCE:
00862                                 {
00863                                         MGACOLL_ITERATE(IMgaFCO,ccpDroppedFCOs) 
00864                                         {                                       
00865                                                 CComPtr<IMgaFCO> ccpNewFco;
00866                                                 HRESULT hr;
00867                                                 if( ( hr = ccpTargetFolder->DeriveRootObject(MGACOLL_ITER,VARIANT_TRUE,&ccpNewFco)) != S_OK) {
00868                                                         if( hr == E_MGA_NOT_DERIVABLE) // typical failure code when subtyping/instantiating
00869                                                         {
00870                                                                 CComBSTR msg( L"Object '"), nm;
00871                                                                 COMTHROW( MGACOLL_ITER->get_Name( &nm));
00872                                                                 COMTHROW(msg.Append( nm));
00873                                                                 COMTHROW(msg.Append( _T("' could not be derived. Some of its ancestors or descendants may be already derived! [Error code E_MGA_NOT_DERIVABLE]")));
00874                                                                 Utils::put2Console( Utils::get_GME( pMgaContext->m_ccpProject), msg, MSG_ERROR);
00875                                                                         pMgaContext->AbortTransaction();//COMTHROW( hr);
00876                                                                 return FALSE;//break; // although it was inside a MGACOLL_ITERATE, we aborted the trans
00877                                                         }
00878                                                         COMTHROW( hr); // otherwise
00879                                                         break;
00880                                                 }
00881                                         }
00882                                         MGACOLL_ITERATE_END;
00883                                         bRetVal=TRUE;                   
00884                                 }break;
00885                                 case DRAGOP_SUBTYPE:
00886                                 {
00887                                         MGACOLL_ITERATE(IMgaFCO,ccpDroppedFCOs) 
00888                                         {                                       
00889                                                 CComPtr<IMgaFCO> ccpNewFco;
00890                                                 HRESULT hr;
00891                                                 if( ( hr = ccpTargetFolder->DeriveRootObject(MGACOLL_ITER,VARIANT_FALSE,&ccpNewFco)) != S_OK) {
00892                                                         //MGATREECTRL_LOGEVENT("    "+fcoName+" cannot be derived.\r\n");
00893                                                         if( hr == E_MGA_NOT_DERIVABLE) // typical failure code when subtyping/instantiating
00894                                                         {
00895                                                                 CComBSTR msg( L"Object '"), nm;
00896                                                                 COMTHROW( MGACOLL_ITER->get_Name( &nm));
00897                                                                 COMTHROW(msg.Append( nm));
00898                                                                 COMTHROW(msg.Append( L"' could not be derived. Some of its ancestors or descendants may be already derived! [Error code E_MGA_NOT_DERIVABLE]"));
00899                                                                 Utils::put2Console( Utils::get_GME( pMgaContext->m_ccpProject), msg, MSG_ERROR);
00900                                                                         pMgaContext->AbortTransaction();//COMTHROW( hr);
00901                                                                 return FALSE;//break; // although it was inside a MGACOLL_ITERATE, we aborted the trans
00902                                                         }
00903                                                         COMTHROW( hr); // otherwise
00904                                                         break;
00905                                                 }
00906                                         }
00907                                         MGACOLL_ITERATE_END;
00908 
00909                                         bRetVal=TRUE;
00910                                 }break;
00911 
00912                                 
00913                         }
00914                 }
00915                 else if(MgaObjectProxy.m_TypeInfo==OBJTYPE_MODEL) // If the drop target is a model
00916                 {
00917                         long fol_cnt = 0;
00918                         if( ccpDroppedFolders)
00919                         {
00920                                 COMTHROW( ccpDroppedFolders->get_Count( &fol_cnt));
00921                                 if ( fol_cnt > 0)
00922                                         AfxMessageBox(_T("Cannot insert folders into a model"));
00923                         }
00924 
00925                         CComQIPtr<IMgaModel> ccpTargetModel(MgaObjectProxy.m_pMgaObject);
00926                         switch(doDragOp)
00927                         {
00928                                 case DRAGOP_MOVE:
00929                                 {
00930 #if(0)          // plain old version
00931                                         CComPtr<IMgaFCOs> ccpNewFCOs;
00932 
00933                                         CComPtr<IMgaMetaRoles> ccpMetaRoles;
00934                                         COMTHROW(ccpMetaRoles.CoCreateInstance(OLESTR("Mga.MgaMetaRoles")));
00935 
00936                                         MGACOLL_ITERATE(IMgaFCO, ccpDroppedFCOs) 
00937                                         {
00938                                                 CComPtr<IMgaFCO> ccpFCO;
00939                                                 COMTHROW(pMgaContext->m_ccpTerritory->OpenFCO(MGACOLL_ITER, &ccpFCO));
00940                                                 CComPtr<IMgaMetaRole> ccpMetaRole;
00941                                                 COMTHROW(ccpFCO->get_MetaRole(&ccpMetaRole));
00942                                                 CComPtr<IMgaMetaFCO> ccpKind;
00943                                                 COMTHROW(ccpFCO->get_Meta(&ccpKind));
00944                                                 CComPtr<IMgaMetaRole> ccpNewRole;
00945 
00946                                                 COMTHROW(ccpMgaResolver->get_RoleByMeta(ccpTargetModel,ccpKind,OBJTYPE_NULL,ccpMetaRole,NULL,&ccpNewRole));
00947                                                 COMTHROW(ccpMetaRoles->Append(ccpNewRole));
00948                                         }
00949                                         MGACOLL_ITERATE_END;
00950                                         COMTHROW( ccpTargetModel->MoveFCOs(ccpDroppedFCOs,ccpMetaRoles,&ccpNewFCOs) );
00951 
00952                                         bRetVal = TRUE;
00953 #else           // check if the target = source
00954                                         CComPtr<IMgaFCOs> ccpNewFCOs;
00955 
00956                                         CComPtr<IMgaMetaRoles> ccpMetaRoles;
00957                                         COMTHROW(ccpMetaRoles.CoCreateInstance(OLESTR("Mga.MgaMetaRoles")));
00958 
00959                                         long fco_cnt = 0;
00960                                         COMTHROW( ccpDroppedFCOs->get_Count( &fco_cnt));
00961                                         if ( fco_cnt > 0)
00962                                         {
00963                                                 bool valid = true;
00964                                                 if ( fco_cnt == 1)
00965                                                 {
00966                                                         valid = false;
00967                                                         CComPtr<IMgaFCO> one_fco;
00968                                                         MGACOLL_ITERATE(IMgaFCO, ccpDroppedFCOs) {
00969                                                                 one_fco = MGACOLL_ITER;
00970                                                         } MGACOLL_ITERATE_END;
00971                                                         VARIANT_BOOL is_equal;
00972                                                         COMTHROW( one_fco->get_IsEqual( ccpTargetModel, &is_equal));
00973 
00974                                                         if (is_equal == VARIANT_FALSE) // not equal
00975                                                                 valid = true;
00976                                                 }
00977 
00978                                                 if ( valid)
00979                                                 {
00980                                                         MGACOLL_ITERATE(IMgaFCO, ccpDroppedFCOs) 
00981                                                         {
00982                                                                 CComPtr<IMgaFCO> ccpFCO;
00983                                                                 COMTHROW(pMgaContext->m_ccpTerritory->OpenFCO(MGACOLL_ITER, &ccpFCO));
00984                                                                 CComPtr<IMgaMetaRole> ccpMetaRole;
00985                                                                 COMTHROW(ccpFCO->get_MetaRole(&ccpMetaRole));
00986                                                                 CComPtr<IMgaMetaFCO> ccpKind;
00987                                                                 COMTHROW(ccpFCO->get_Meta(&ccpKind));
00988                                                                 
00989                                                                 IMgaMetaRolePtr ccpNewRole = ccpMgaResolver->RoleByMeta[ccpTargetModel,ccpKind,OBJTYPE_NULL,ccpMetaRole,NULL];
00990                                                                 COMTHROW(ccpMetaRoles->Append(ccpNewRole));
00991                                                         }
00992                                                         MGACOLL_ITERATE_END;
00993 
00994                                                         COMTHROW( ccpTargetModel->MoveFCOs(ccpDroppedFCOs,ccpMetaRoles,&ccpNewFCOs) );
00995                                                         bRetVal = TRUE;
00996                                                 }
00997                                                 else bRetVal = FALSE;
00998                                         }
00999                                         else bRetVal=FALSE; //?
01000 #endif
01001 
01002                                 }break;
01003                                 case DRAGOP_COPY:
01004                                 {
01005                                         CComPtr<IMgaFCOs> ccpNewFCOs;
01006 
01007                                         CComPtr<IMgaMetaRoles> ccpMetaRoles;
01008                                         COMTHROW(ccpMetaRoles.CoCreateInstance(OLESTR("Mga.MgaMetaRoles")));
01009 
01010                                         MGACOLL_ITERATE(IMgaFCO, ccpDroppedFCOs) 
01011                                         {
01012                                                 CComPtr<IMgaFCO> ccpFCO;
01013                                                 COMTHROW(pMgaContext->m_ccpTerritory->OpenFCO(MGACOLL_ITER, &ccpFCO));
01014                                                 CComPtr<IMgaMetaRole> ccpMetaRole;
01015                                                 COMTHROW(ccpFCO->get_MetaRole(&ccpMetaRole));
01016                                                 CComPtr<IMgaMetaFCO> ccpKind;
01017                                                 COMTHROW(ccpFCO->get_Meta(&ccpKind));
01018                                                 IMgaMetaRolePtr ccpNewRole;
01019 
01020                                                 ccpNewRole = ccpMgaResolver->RoleByMeta[ccpTargetModel,ccpKind,OBJTYPE_NULL,ccpMetaRole,NULL];
01021                                                 COMTHROW(ccpMetaRoles->Append(ccpNewRole));
01022                                         }
01023                                         MGACOLL_ITERATE_END;
01024                                         COMTHROW( ccpTargetModel->CopyFCOs(ccpDroppedFCOs,ccpMetaRoles,&ccpNewFCOs) );
01025 
01026                                         MGACOLL_ITERATE(IMgaFCO, ccpNewFCOs) { // for smart copy related entries
01027                                                 MakeSureGUIDIsUniqueForSmartCopy( CComPtr<IMgaFCO>( MGACOLL_ITER) );
01028                                         } MGACOLL_ITERATE_END;
01029                                         
01030                                         bRetVal=TRUE;
01031 
01032                                 }break;
01033                                 case DRAGOP_REFERENCE:
01034                                 {                                               
01035 
01036                                                         CComBSTR bszSourceName;
01037 
01038                                                         MGACOLL_ITERATE(IMgaFCO,ccpDroppedFCOs)
01039                                                         {
01040                                                                 //-acquiring a pointer in the active territory for MGACOLL_ITER
01041                                                                 CComPtr<IMgaFCO> ccpFCO;
01042                                                                 COMTHROW(pMgaContext->m_ccpTerritory->OpenFCO(MGACOLL_ITER, &ccpFCO));
01043 
01044                                                                 CComPtr<IMgaConnection> conn;
01045                                                                 if(ccpFCO.QueryInterface(&conn) != S_OK) { // skip connections, they cannot be referenced
01046                                                                         CComPtr<IMgaMetaRole> ccpNewMetaRole;
01047                                                                         COMTHROW( ccpMgaResolver->get_RefRoleByMeta(ccpTargetModel, NULL, ccpFCO, &ccpNewMetaRole) );
01048 
01049                                                                         if(ccpNewMetaRole == 0)
01050                                                                         {
01051                                                                                 MGATREECTRL_LOGEVENT("    Cannot create reference.\r\n");
01052                                                                         }
01053                                                                         else {
01054                                                                                 CComPtr<IMgaFCO> ccpNewFCO;
01055                                                                                 COMTHROW( ccpTargetModel->CreateReference(ccpNewMetaRole,ccpFCO,&ccpNewFCO) );
01056                                                                                 ASSERT(ccpNewFCO != NULL);
01057 
01058                                                                                 // Creating name for the new reference:
01059                                                                                 bszSourceName.Empty();
01060                                                                                 COMTHROW( ccpFCO->get_Name(&bszSourceName) );
01061                                                                                 /*
01062                                                                                 // ReferencedName+"Ref"
01063                                                                                 CString strSourceName(bszSourceName);
01064                                                                                 strSourceName += "Ref";
01065                                                                                 bszSourceName = strSourceName;*/ // commented by zolmol according to DoPasteNative() logic in GMEView.cpp 
01066 
01067                                                                                 //Rename
01068                                                                                 COMTHROW( ccpNewFCO->put_Name(bszSourceName));
01069                                                                         }
01070                                                                 }
01071                                                         }MGACOLL_ITERATE_END;
01072                                                         
01073                                                         bRetVal=TRUE;
01074                                 }break;
01075                                 case DRAGOP_INSTANCE:
01076                                 case DRAGOP_SUBTYPE:
01077                                 {
01078                                         HRESULT hr = S_OK;
01079                                         bool excep_handled = false;
01080                                         MGACOLL_ITERATE(IMgaFCO,ccpDroppedFCOs) {
01081                                                 
01082                                                 //-acquiring a pointer in the active territory for MGACOLL_ITER
01083                                                 CComPtr<IMgaFCO> ccpFCO;
01084                                                 COMTHROW(pMgaContext->m_ccpTerritory->OpenFCO(MGACOLL_ITER, &ccpFCO));
01085 
01086                                                 CComBSTR bstr;
01087                                                 COMTHROW(ccpFCO->get_Name(&bstr));
01088                                                 CString fcoName;
01089                                                 CopyTo(bstr,fcoName);
01090 
01091                                                 CComPtr<IMgaMetaFCO> ccpMetaFCO;
01092                                                 COMTHROW( ccpFCO->get_Meta(&ccpMetaFCO) );
01093                                                 ASSERT( ccpMetaFCO != NULL);
01094 
01095                                                 // Old role can be NULL
01096                                                 CComPtr<IMgaMetaRole> ccpOldMetaRole;
01097                                                 COMTHROW( ccpFCO->get_MetaRole(&ccpOldMetaRole) );
01098                                                 
01099                                                 CComPtr<IMgaMetaRole> ccpNewMetaRole;
01100                                                 COMTHROW( ccpMgaResolver->get_RoleByMeta(ccpTargetModel, ccpMetaFCO, OBJTYPE_NULL, ccpOldMetaRole, NULL, &ccpNewMetaRole) );
01101                                                 if(ccpNewMetaRole == 0)
01102                                                 {
01103                                                         MGATREECTRL_LOGEVENT("    Cannot insert object derived from "+fcoName+"\r\n");
01104                                                 }
01105                                                 else {
01106                                                         CComPtr<IMgaFCO> ccpNewFCO;
01107                                                         VARIANT_BOOL inst = doDragOp == DRAGOP_INSTANCE? VARIANT_TRUE : VARIANT_FALSE;
01108                                                         if((hr = ccpTargetModel->DeriveChildObject(ccpFCO,ccpNewMetaRole, inst ,&ccpNewFCO)) != S_OK) {
01109                                                                 MGATREECTRL_LOGEVENT("    "+fcoName+" cannot be derived.\r\n");
01110                                                                 if( hr == E_MGA_NOT_DERIVABLE) // typical failure code when subtyping/instantiating
01111                                                                 {
01112                                                                         CComBSTR msg( L"Object '"), nm;
01113                                                                         COMTHROW( ccpFCO->get_Name( &nm));
01114                                                                         COMTHROW(msg.Append( nm));
01115                                                                         COMTHROW(msg.Append( L"' could not be derived. Some of its ancestors or descendants may be already derived! [Error code E_MGA_NOT_DERIVABLE]"));
01116                                                                         Utils::put2Console( Utils::get_GME( pMgaContext->m_ccpProject), msg, MSG_ERROR);
01117 
01118                                                                         pMgaContext->AbortTransaction();//COMTHROW( hr);
01119                                                                         return FALSE;//break; // although it was inside a MGACOLL_ITERATE, we aborted the trans
01120                                                                 }
01121                                                                 COMTHROW( hr); // otherwise
01122                                                                 break;
01123                                                         }
01124                                                 }
01125 
01126                                         }
01127                                         MGACOLL_ITERATE_END;
01128                                         bRetVal=TRUE;
01129                                 }break;
01130                                 
01131                         }
01132                 }
01133                 pMgaContext->CommitTransaction();
01134 
01135         }MSGCATCH(_T("Error completing drop operation"), pMgaContext->AbortTransaction();)      
01136 
01137 
01138 
01139         return bRetVal;
01140 }
01141 
01142 BOOL CAggregateTreeCtrl::DoDropWithoutChecking(eDragOperation doDragOp, COleDataObject *pDataObject, CPoint point)
01143 {
01144         MGATREECTRL_LOGEVENT("CAggregateTreeCtrl::DoDropWithoutChecking\r\n");
01145 
01146         CGMEActiveBrowserApp* pApp = (CGMEActiveBrowserApp*)AfxGetApp();
01147         CMgaContext* pMgaContext = &pApp->m_CurrentProject.m_MgaContext;
01148 
01149         CComPtr<IMgaComponentEx> constrMgr;
01150         if (pMgaContext)
01151                 constrMgr = pMgaContext->FindConstraintManager();
01152         if (constrMgr)
01153                 COMTHROW(constrMgr->Enable(false));
01154         BOOL res = DoDrop( doDragOp, pDataObject, point);
01155         if (constrMgr) {
01156                 COMTHROW(constrMgr->Enable(true));
01157 //              constrMgr.Release();
01158         }
01159 
01160         return res;
01161 }
01162 
01163 static void ImageList_AddGdiplusBitmap(HIMAGELIST imageList, Gdiplus::Bitmap& bmp, Gdiplus::Color color=Gdiplus::Color(Gdiplus::Color::White))
01164 {
01165         using namespace Gdiplus;
01166         RectF bounds;
01167         Unit unit(UnitPixel);
01168         VERIFY(bmp.GetBounds(&bounds, &unit) == Ok);
01169         HBITMAP hBmp;
01170 
01171         if (bounds.X == 16 && bounds.Y == 16)
01172         {
01173                 VERIFY(bmp.GetHBITMAP(color, &hBmp) == Ok);
01174         }
01175         else
01176         {
01177                 Image* thumb = bmp.GetThumbnailImage(16, 16);
01178                 Bitmap bmpThumb(16, 16);
01179                 Graphics* graphics = Graphics::FromImage(&bmpThumb);
01180                 VERIFY(graphics->GetLastStatus() == Ok);
01181                 VERIFY(graphics->Clear(color) == Ok);
01182                 VERIFY(graphics->DrawImage(thumb, 0, 0, 0, 0, 16, 16, UnitPixel) == Ok);
01183                 VERIFY(bmpThumb.GetHBITMAP(color, &hBmp) == Ok);
01184                 delete thumb;
01185                 delete graphics;
01186         }
01187         
01188         ImageList_Add(imageList, hBmp, 0);
01189         DeleteObject(hBmp);
01190 }
01191 
01192 void CAggregateTreeCtrl::GetCustomTreeIcon(IMgaObject* ccpMgaObject, TVITEM& tvItem)
01193 {
01194         CGMEActiveBrowserApp* pApp=(CGMEActiveBrowserApp*)AfxGetApp();
01195         CMgaContext* pMgaContext=&pApp->m_CurrentProject.m_MgaContext;
01196         pMgaContext->BeginTransaction();
01197         CComPtr<IMgaMetaBase> meta;
01198         COMTHROW(ccpMgaObject->get_MetaBase(&meta));
01199         _bstr_t treeIcon;
01200         meta->get_RegistryValue(CComBSTR(L"treeIcon"), treeIcon.GetAddress());
01201         _bstr_t expandedTreeIcon;
01202         meta->get_RegistryValue(CComBSTR(L"expandedTreeIcon"), expandedTreeIcon.GetAddress());
01203         pMgaContext->CommitTransaction();
01204 
01205 
01206         CComPtr<IMgaProject> project;
01207         COMTHROW(ccpMgaObject->get_Project(&project));
01208         PathUtil pathUtil;
01209 
01210         std::unique_ptr<Gdiplus::Bitmap> treeIconBmp(nullptr);
01211         std::unique_ptr<Gdiplus::Bitmap> expandedTreeIconBmp(nullptr);
01212         if (treeIcon.length())
01213         {
01214                 auto it = treeIcons.find(treeIcon);
01215                 if (it != treeIcons.end() && it->second != 0)
01216                 {
01217                         tvItem.iSelectedImage = tvItem.iImage = it->second;
01218                         return;
01219                 }
01220         }
01221 
01222         if (treeIcon.length() && pathUtil.loadPaths(project, true))
01223         {
01224                 std::vector<CString> paths = pathUtil.getPaths();
01225                 for (auto pathsIt = paths.begin(); pathsIt != paths.end(); pathsIt++)
01226                 {
01227                         if (treeIconBmp == nullptr)
01228                         {
01229                                 treeIconBmp = 
01230                                         std::unique_ptr<Gdiplus::Bitmap>(Gdiplus::Bitmap::FromFile(*pathsIt + L"\\" + static_cast<const wchar_t*>(treeIcon)));
01231                                 if (treeIconBmp->GetLastStatus() != Gdiplus::Ok)
01232                                 {
01233                                         treeIconBmp = nullptr;
01234                                 }
01235                         }
01236                         if (expandedTreeIcon.length() != 0 && expandedTreeIconBmp == nullptr)
01237                         {
01238                                 expandedTreeIconBmp = 
01239                                         std::unique_ptr<Gdiplus::Bitmap>(Gdiplus::Bitmap::FromFile(*pathsIt + L"\\" + static_cast<const wchar_t*>(expandedTreeIcon)));
01240                                 if (expandedTreeIconBmp->GetLastStatus() != Gdiplus::Ok)
01241                                 {
01242                                         expandedTreeIconBmp = nullptr;
01243                                 }
01244                         }
01245                 }
01246         }
01247         if (treeIconBmp != nullptr)
01248         {
01249                 CImageList* imageList = GetImageList(TVSIL_NORMAL);
01250 
01251                 ImageList_AddGdiplusBitmap(static_cast<HIMAGELIST>(*imageList), *treeIconBmp.get());
01252                 ImageList_AddGdiplusBitmap(static_cast<HIMAGELIST>(*imageList), expandedTreeIconBmp != nullptr ? *expandedTreeIconBmp.get() : *treeIconBmp.get());
01253 
01254                 tvItem.iSelectedImage = tvItem.iImage = imageList->GetImageCount() - 2;
01255                 treeIcons.insert(std::make_pair(treeIcon, imageList->GetImageCount() - 2));
01256                 if (expandedTreeIcon.length() != 0)
01257                         treeIcons.insert(std::make_pair(treeIcon, imageList->GetImageCount()));
01258         } 
01259         else
01260         {
01261                 treeIcons.insert(std::make_pair(treeIcon, 0));
01262         }
01263 
01264 }
01265 
01266 
01267 void CAggregateTreeCtrl::SetItemProperties(HTREEITEM hItem, int p_fileLatentState, CAggregateMgaObjectProxy* insertedProxy)
01268 {
01269 
01270 
01271         CAggregateMgaObjectProxy ObjectProxy;
01272 
01273         if(!m_MgaMap.LookupObjectProxy(hItem, ObjectProxy))
01274                 return;
01275 
01276         CComQIPtr<IMgaObject> ccpObject(ObjectProxy.m_pMgaObject);
01277 
01278         if(!ccpObject)
01279                 return; // Not an MgaObject
01280         
01281 
01282         BYTE cState=0;
01283 
01284         CGMEActiveBrowserApp* pApp=(CGMEActiveBrowserApp*)AfxGetApp();
01285         CMgaContext* pMgaContext=&pApp->m_CurrentProject.m_MgaContext;
01286 
01287         pMgaContext->BeginTransaction();
01288 
01289 
01290         // Checking access rights
01291         VARIANT_BOOL vtbIsWritable=VARIANT_FALSE;
01292         VARIANT_BOOL vtbIsReadOnly=VARIANT_FALSE;
01293         COMTHROW( ccpObject->get_IsWritable(&vtbIsWritable));
01294         COMTHROW( ccpObject->HasReadOnlyAccess( &vtbIsReadOnly));
01295 
01296         if (vtbIsWritable != VARIANT_TRUE || vtbIsReadOnly == VARIANT_TRUE || p_fileLatentState != 0)
01297         {
01298                 // Read only object
01299                 cState|=0x0001;
01300         }
01301         else
01302         {
01303                 // If the object is writable
01304 
01305                 
01306         }
01307 
01308 
01309         VARIANT_BOOL vtbIsLibObject=VARIANT_FALSE;;
01310         COMTHROW(ccpObject->get_IsLibObject(&vtbIsLibObject));
01311         
01312         if(vtbIsLibObject!=VARIANT_TRUE)
01313         {
01314                 // Not a LibObject
01315         }
01316         else
01317         {
01318                 // LibObject
01319                 cState|=0x0002;
01320 
01321         }
01322 
01323 
01324         CComQIPtr<IMgaObject> ccpMgaObject(ObjectProxy.m_pMgaObject);
01325         if (ccpMgaObject)
01326         {
01327                 CComBSTR id;
01328                 ccpMgaObject->get_ID(&id);
01329                 auto it = m_highlightedObjects.find(id);
01330                 if (it != m_highlightedObjects.end())
01331                 {
01332                         CTreeCtrl::SetItemState(hItem, TVIS_BOLD, TVIS_BOLD);
01333                 }
01334                 else
01335                 {
01336                         CTreeCtrl::SetItemState(hItem, 0, TVIS_BOLD);
01337                 }
01338         }
01339 
01341         // If not an Folder deal with Subtype/instance flags
01342         if(ObjectProxy.m_TypeInfo!=OBJTYPE_FOLDER) 
01343         {
01344                 CComQIPtr<IMgaFCO> ccpMgaFCO(ObjectProxy.m_pMgaObject);
01345                 if(!ccpMgaFCO)
01346                         return; // Not an FCO
01347 
01348                 // Is it instance?
01349                 VARIANT_BOOL vtbIsInstance=VARIANT_FALSE;
01350                 COMTHROW(ccpMgaFCO->get_IsInstance(&vtbIsInstance));
01351 
01352                 if(vtbIsInstance!=VARIANT_TRUE)
01353                 {
01354                         CComPtr<IMgaFCO> ccpBaseType;
01355                         COMTHROW(ccpMgaFCO->get_BaseType(&ccpBaseType));
01356 
01357                         if(!ccpBaseType)
01358                         {
01359                                 // Not derived
01360                         }
01361                         else
01362                         {
01363                                 // Derived
01364                                 cState|=0x0008;
01365                         }
01366 
01367                 }
01368                 else
01369                 {
01370                         // Instance
01371                         cState|=0x0004;
01372 
01373                 }
01374 
01375         } // if not folder
01376         pMgaContext->CommitTransaction();
01377         
01378 
01379         if(cState)
01380         {
01381                 CTreeCtrl::SetItemState( hItem,INDEXTOSTATEIMAGEMASK(cState), TVIS_STATEIMAGEMASK );
01382         }
01383         else
01384         {               
01385                 CTreeCtrl::SetItemState( hItem,0, TVIS_STATEIMAGEMASK );
01386         }
01387 }
01388 
01389 
01390 
01391 BOOL CAggregateTreeCtrl::IsLibrary(LPUNKNOWN pUnknown, bool *p_ptrHasAnyDependency /*= 0*/)
01392 {
01393 
01394         CComQIPtr<IMgaFolder> ccpFolder(pUnknown);
01395         
01396         if(!ccpFolder)return FALSE;
01397 
01398                 
01399         CGMEActiveBrowserApp* pApp=(CGMEActiveBrowserApp*)AfxGetApp();
01400         CMgaContext* pMgaContext=&pApp->m_CurrentProject.m_MgaContext;
01401 
01402         pMgaContext->BeginTransaction();
01403 
01404         CComBSTR bszLibName;                                            
01405         COMTHROW(ccpFolder->get_LibraryName(&bszLibName));
01406 
01407         if( bszLibName && p_ptrHasAnyDependency)  // user interested in the dependency status
01408         {
01409                 *p_ptrHasAnyDependency = IsUngroupedLibrary( ccpFolder);
01410         }
01411 
01412         pMgaContext->CommitTransaction();
01413 
01414         if(!bszLibName)
01415         {       
01416                 return FALSE;
01417         }
01418 
01419         return TRUE;
01420 
01421 }
01422 
01423 //static
01424 bool CAggregateTreeCtrl::IsUngroupedLibrary(CComPtr<IMgaFolder> pLibPtr)
01425 {
01426         ASSERT( pLibPtr);
01427         if( !pLibPtr) return false;
01428 
01429         bool retv = true;
01430         CComPtr<IMgaFolders> c1, c2;
01431         COMTHROW( pLibPtr->GetVirtuallyIncludedBy( &c1));
01432         COMTHROW( pLibPtr->GetVirtuallyIncludes( &c2));
01433         long l1( 0), l2( 0);
01434         if( c1) COMTHROW( c1->get_Count( &l1));
01435         if( c2) COMTHROW( c2->get_Count( &l2));
01436         if( l1 == 0 && l2 == 0)
01437         {
01438                 retv = false;
01439         }
01440 
01441         return retv;
01442 }
01443