AcDbObjectId OarxEmployeeService::getAppDictionary () { AcDbDictionary *pNOD =NULL ; AcDbDictionary *pFirmDict =NULL ; AcDbDictionary *pAppDict =NULL ; try { //----- Get hold of the NOD ARXOK ( getNOD (pNOD, AcDb::kForRead) ) ; //----- Get our Firm Dictionary AcDbObjectId id0 ; if ( pNOD->getAt (OARX_FIRM_DICT, id0) == Acad::eKeyNotFound ) { //----- Then create it pFirmDict =new AcDbDictionary ; if ( pFirmDict == NULL ) throw Acad::eOutOfMemory ; ARXOK ( pNOD->upgradeOpen () ) ; ARXOK ( pNOD->setAt (OARX_FIRM_DICT, pFirmDict, id0) ) ; } else { //----- Open the dictionary ARXOK ( acdbOpenAcDbObject ((AcDbObject *&)pFirmDict, id0, AcDb::kForRead) ) ; } //----- Get our App Dictionary if ( pFirmDict->getAt (OARX_APP_DICT, id0) == Acad::eKeyNotFound ) { //----- Then create it pAppDict =new AcDbDictionary ; if ( pAppDict == NULL ) throw Acad::eOutOfMemory ; if ( pFirmDict->isWriteEnabled () == false ) ARXOK ( pFirmDict->upgradeOpen () ) ; ARXOK ( pFirmDict->setAt (OARX_APP_DICT, pAppDict, id0) ) ; id0 =pAppDict->objectId () ; } pNOD->close () ; pFirmDict->close () ; pAppDict->close () ; return (id0) ; } catch (const Acad::ErrorStatus es) { if ( pNOD != NULL ) pNOD->cancel () ; if ( pFirmDict != NULL && pFirmDict->objectId () == AcDbObjectId::kNull ) delete pFirmDict ; else if ( pFirmDict != NULL ) pFirmDict->cancel () ; if ( pAppDict != NULL && pAppDict->objectId () == AcDbObjectId::kNull ) delete pAppDict ; else pAppDict->cancel () ; return (AcDbObjectId::kNull) ; } }
Acad::ErrorStatus CTwArxDictionary::CreateSubDictionaryID( IN const AcDbObjectId& IdRoot, IN const CString& strKey, OUT AcDbObjectId& IdSubDic, IN AcRxClass* pRxObjType /*= AcDbDictionary::desc() */ ) const { if( pRxObjType == NULL ) return Acad::eNullObjectPointer; Acad::ErrorStatus es = Acad::eOk; AcDbDictionary* pDicRoot = NULL; AcDbDatabase* pWdb = acdbCurDwg(); if( IdRoot.isNull() ) es = pWdb->getNamedObjectsDictionary( pDicRoot, AcDb::kForRead ); else es = acdbOpenObject( pDicRoot, IdRoot, AcDb::kForRead ); if( es != Acad::eOk ) return es; if( pDicRoot->has(strKey) ) { pDicRoot->getAt( strKey, IdSubDic ); pDicRoot->close(); return es; } pDicRoot->upgradeOpen(); AcDbObject* pObj = (AcDbObject*)pRxObjType->create(); es = pDicRoot->setAt( strKey, pObj, IdSubDic ); pObj->close(); pDicRoot->close(); return es; }
// Adds the reactor to the editor to monitor changes. // void setup() { acedEditor->addReactor(gpEdReac); acutPrintf("Added new command to Wblock.\n"); // Now, for this sample only, we need to create a // new dictionary, add it to the named object // dictionary using the key string specified by the // constant pointer kpDictionary. Then we'll create // a couple of empty xrecords and put them into the // new dictionary. All of this provides the objects // that our code will be cloning across. // AcDbDictionary *pNamedobj; acdbHostApplicationServices()->workingDatabase() ->getNamedObjectsDictionary(pNamedobj, AcDb::kForRead); AcDbDictionary *pDict; // Search for the dictionary associated with the key // kpDictionary. If it's not found, then create it, // add it to the namedobjects dictionary, and then // create and add a few xrecords to it. // // If it is found then do nothing because it's already // been done sometime previously. // if (!pNamedobj->has(kpDictionary)) { if (pNamedobj->upgradeOpen() == Acad::eOk) { pDict = new AcDbDictionary; AcDbObjectId DictId; pNamedobj->setAt(kpDictionary, pDict, DictId); pNamedobj->close(); AcDbXrecord *pObj1 = new AcDbXrecord(), *pObj2 = new AcDbXrecord(); AcDbObjectId rId1, rId2; pDict->setAt("OBJ1", pObj1, rId1); pDict->setAt("OBJ2", pObj2, rId2); pObj1->close(); pObj2->close(); pDict->close(); } else pNamedobj->close(); } }
void ArxDbgAppEditorReactor::insertCloneOwnerDict(const AcDbObjectId& dictId, AcDbDatabase* destDb, AcDbIdMapping& idMap) { // the dictionaries are dealt with as a whole when encountering the // first entry within them. Skip processing if we have already // encountered this one before. if (m_didTheseDicts.contains(dictId)) return; else m_didTheseDicts.append(dictId); // get the name of the dictionary to recreate CString dictName; if (!ArxDbgUtils::lookUpDictEntryName(dictId, dictName)) { ArxDbgUtils::stopAlertBox(_T("ERROR: Couldn't find old dictionary name during Insert!")); return; } // open the source dictionary to be inserted AcDbDictionary* srcDict; if (acdbOpenObject(srcDict, dictId, AcDb::kForRead) != Acad::eOk) { ASSERT(0); return; } // try to open the destiniation dictionary. Since INSERT does // not clone the destination NamedObjects dictionary, we can // use getAt() on it since IDs are not inFlux Acad::ErrorStatus es; AcDbDictionary* destDict = ArxDbgUtils::openDictionaryForRead(dictName, destDb); if (destDict) { es = destDict->upgradeOpen(); if (es == Acad::eOk) insertCloneMergeDicts(srcDict, destDict, idMap); else { ASSERT(0); } destDict->close(); } else { // our dictionary doesn't yet exist in destination database. // Use deepClone to clone it and all of its contents to the // root dictionary of the destination database. AcDbDictionary* rootDictDest; es = destDb->getNamedObjectsDictionary(rootDictDest, AcDb::kForWrite); if (es == Acad::eOk) { AcDbObject* pClone = NULL; srcDict->deepClone(rootDictDest, pClone, idMap); if (pClone != NULL) { AcDbObjectId tmpObjId; es = rootDictDest->setAt(dictName, pClone, tmpObjId); if (es != Acad::eOk) { ArxDbgUtils::stopAlertBox(_T("ERROR: Could not clone destination dictionary!")); ArxDbgUtils::rxErrorAlert(es); } pClone->close(); } rootDictDest->close(); } } srcDict->close(); }
// AsdkNODEdReactor is derived from AcEditorReactor // void AsdkNODEdReactor::beginDeepCloneXlation( AcDbIdMapping& idMap, Acad::ErrorStatus* pRetStat) { Acad::ErrorStatus es; AcDbObjectId dictId; if ( idMap.deepCloneContext() != AcDb::kDcWblock && idMap.deepCloneContext() != AcDb::kDcInsert) return; // Get the "from" and "to" databases. // AcDbDatabase *pFrom, *pTo; idMap.origDb(pFrom); idMap.destDb(pTo); // See if the "from" database has our dictionary, and // open it. If it doesn't have one, we are done. // AcDbDictionary *pSrcNamedObjDict; pFrom->getNamedObjectsDictionary(pSrcNamedObjDict, AcDb::kForRead); es = pSrcNamedObjDict->getAt(kpDictionary, dictId); pSrcNamedObjDict->close(); if (es == Acad::eKeyNotFound) return; AcDbDictionary *pSrcDict; acdbOpenObject(pSrcDict, dictId, AcDb::kForRead); AcDbObject *pClone; switch (idMap.deepCloneContext()) { case AcDb::kDcWblock: // WBLOCK clones all, or part of a drawing into a // newly created drawing. This means that the // NamedObject Dictionary is always cloned, and // its AcDbObjectIds are in flux. Therefore, you // cannot use getAt() or setAt() on the dictionary // in the new database. This is because the // cloned dictionary references all refer to the // original objects. During Deep Clone translation, // all cloned entries will be translated to the // new objects, and entries not cloned will be // "removed" by getting "translated" to NULL. // // The cloning of entries in our own dictionary are // not handled here. If all are to be cloned, then // call setTreatElementsAsHard(Adesk::kTrue) on the // dictionary. Otherwise, only those entries which // are refered to by hard references in other // wblocked objects, will have been cloned via // those references. // In this example, we will always write out all of // the records. Since TreatElementsAsHard is not // currently persistent, we reset it here each time. // pSrcDict->upgradeOpen(); pSrcDict->setTreatElementsAsHard(Adesk::kTrue); pClone = NULL; pSrcDict->wblockClone(pTo, pClone, idMap, Adesk::kFalse); if (pClone != NULL) pClone->close(); break; case AcDb::kDcInsert: // In INSERT, an entire drawing is cloned, and // "merged" into a pre-existing drawing. This // means that the destination drawing may already // have our dictionary - in which case we have to // merge our entries into the destination // dictionary. So, first we must find out if // the destination NamedObjects dictionary has // our dictionary. // AcDbDictionary *pDestNamedDict; pTo->getNamedObjectsDictionary(pDestNamedDict, AcDb::kForWrite); // Since INSERT does not clone the destination // NamedObjects dictionary, we can use getAt() // on it. // es = pDestNamedDict->getAt(kpDictionary, dictId); // If our dictionary does not yet exist in the // NamedObjects dictionary, which is not itself // cloned, we have to both clone and add our // dictionary to it. Since dictionary entries are // ownership references, all of our entries will // also be cloned at this point, so we are done. // if (es == Acad::eKeyNotFound) { pClone = NULL; pSrcDict->deepClone(pDestNamedDict, pClone, idMap); // Unless we have overridden the deepClone // of our dictionary, we should expect it to // always be cloned here. // if (pClone == NULL) { *pRetStat = Acad::eNullObjectId; break; } pDestNamedDict->setAt(kpDictionary, pClone, dictId); pDestNamedDict->close(); pClone->close(); break; } pDestNamedDict->close(); // Our dictionary already exists in the destination // database, so now we must "merge" the entries // into it. Since we have not cloned our // destination dictionary, its objectIds are not in // flux, and we can use getAt() and setAt() on it. // AcDbDictionary *pDestDict; acdbOpenObject(pDestDict, dictId, AcDb::kForWrite); AcDbObject *pObj, *pObjClone; AcDbDictionaryIterator* pIter; pIter = pSrcDict->newIterator(); for (; !pIter->done(); pIter->next()) { const char *pName = pIter->name(); pIter->getObject(pObj, AcDb::kForRead); // If the dictionary contains any references // and/or other objects have references to it, // you must either use deepClone() or put the // idPairs into the idMap here, so that they // will be in the map for translation. // pObjClone = NULL; pObj->deepClone(pDestDict, pObjClone, idMap); // INSERT usually uses a method of cloning // called CheapClone, where it "moves" objects // into the destination database instead of // actually cloning them. When this happens, // pObj and pObjClone are pointers to the // same object. We only want to close pObj // here if it really is a different object. // if (pObj != pObjClone) pObj->close(); if (pObjClone == NULL) continue; // If the name already exists in our // destination dictionary, it must be changed // to something unique. In this example, the // name is changed to an annonymous entry. // The setAt() method will automatically append // a unique identifier to each name beginning // with "*". It will become something like, // "*S04". // if ( pDestDict->getAt(pName, dictId) == Acad::eKeyNotFound) pDestDict->setAt(pName, pObjClone, dictId); else pDestDict->setAt("*S", pObjClone, dictId); pObjClone->close(); } delete pIter; pDestDict->close(); break; default: break; } pSrcDict->close(); }