dgnlib levels and levelIDs

I am using a Level combo box selector in my mdl program.  In my hook function I set up the combo box attibutes to show level libraries.  My issue is that the same level in my dgnlib returns a different levelID in one file as opposed to another, so it is not consistent between files.  Since I have assigned a number in my dgnlib to each level, is it possible to store the levelCode (number) instead of the levelID which microstation generates on its own?   What is the best approach here?

Thanks
Ray

Parents
  • Levels: Names, Codes & IDs

    Ray:

    The same level in my dgnlib returns a different levelID in one file as opposed to another …

    Your observation is as expected: unless one file is a clone of another, you cannot expect level IDs to be the same across different DGN files. There's some more about levels and MDL.

    Ray:

    Since I have assigned a number in my dgnlib to each level, is it possible to store the levelCode (number) instead of the levelID which MicroStation generates on its own?

    Both the level name and the level code are user-assigned. Each must be unique per DGN file, so you should work with either of those two. Regard the level ID as a temporary value valid while working in a single DgnModelRefP.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

Reply
  • Levels: Names, Codes & IDs

    Ray:

    The same level in my dgnlib returns a different levelID in one file as opposed to another …

    Your observation is as expected: unless one file is a clone of another, you cannot expect level IDs to be the same across different DGN files. There's some more about levels and MDL.

    Ray:

    Since I have assigned a number in my dgnlib to each level, is it possible to store the levelCode (number) instead of the levelID which MicroStation generates on its own?

    Both the level name and the level code are user-assigned. Each must be unique per DGN file, so you should work with either of those two. Regard the level ID as a temporary value valid while working in a single DgnModelRefP.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

Children
  • Jon,

    How do I get it to use the level codes when I do the mdlLevelList_getLevelNamesListModelEx?  After I load it should I go back through it and get the level codes for each levelID and replace them?

    Here is my create for the item:

    ULong listAttr = LEVELLIST_SHOW_LEVEL_LIBRARIES | LEVELLIST_BOLD_USED;
    dimP->msgUnderstood = TRUE;

    switch (dimP->messageType)
    {
    case DITEM_MESSAGE_CREATE:
    {
    int numCols=1;
    ListModel *pListModel;

    if (NULL == (pListModel = mdlListModel_create (numCols)))
    {
    dimP->u.create.createFailed = TRUE;
    break;
    }

    if (SUCCESS != mdlLevelList_getLevelNamesListModelEx (pListModel, MASTERFILE, sadiInfo.project.photoLevelOdd, listAttr))
    {
    mdlListModel_destroy (pListModel, TRUE);
    dimP->u.create.createFailed = TRUE;
    break;
    }

    mdlDialog_comboBoxSetListModelP (dimP->dialogItemP->rawItemP, pListModel);
    break;
    }

     

  • Ray:

    How do I get it to use the level codes when I do the mdlLevelList_getLevelNamesListModelEx?

    It's curious that those functions ignore the level code. Why don't they build a two-column ListModel that stores both the name and the code for each level?

    I suggest that you use mdlLevelList_getLevelNamesListModelEx to build a temporary ListModel. Then, create another two-column ListModel to store the name and the code for each level. Copy the contents of the temporary ListModel to the enhanced ListModel. That way, you have a universal ListModel that you can use again.

    You can assign the underlying level ID to each ListRow's internal user data (mdlListRow_setAppData). Then assign that to your Combo's ListBox. Adjust the Combo's columns to make visible either the level name, code, or both.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • Jon,

    Thanks for the info.  I have another question it there any way to determine whether the level came from a library or the active file once loaded into the combo item?  My issue here is that for legacy purposes I created a level lib with named levels and codes between 1-63.  Now if for example I have a level named 'Road' on code 10 and the old 'Level 10' level which is also code 10 is in the list, my combo is going to show the 'Level 10' first because that is the first it will come to in the list.

    So that is why I though if I could sort the list by level library I could put all my new named levels at the top so it would alway find them first.

    By the way I also lose my BOLD_USED attribute when copying to my new list model.  Perhaps the mdlListRow_setAppData would take care of that, but I wasn't sure how to get it to work.

    Here is my code:

    if (SUCCESS != mdlLevelList_getLevelNamesListModelEx (pListModel, MASTERFILE, sadiInfo.project.photoLevelOdd, listAttr))
    {
    mdlListModel_destroy (pListModel, TRUE);
    dimP->u.create.createFailed = TRUE;
    break;
    }
    if (NULL != (enhanceListModel = mdlListModel_create (numCols))) {
    mdlListModel_sort(pListModel,TRUE,0,-1,0);
    for (i=0;i<mdlListModel_getRowCount(pListModel) ;i++)
     {
    ListCell *pCell;
    ListRow *pRow,*pRowAdd;
    ValueDescr val;
    LevelCode levelCode;
    char levelString[MAX_LEVEL_NAME_LENGTH];
    MSWChar levelNameOutput[MAX_LEVEL_NAME_LENGTH];

    pRow = mdlListModel_getRowAtIndex (pListModel, i);
    pCell = mdlListRow_getCellAtIndex (pRow, 0);

    mdlListCell_getValue (pCell,&val);
    if(SUCCESS!=mdlLevel_getCode (&levelCode,mdlModelRef_getActive(),val.value.sLongFormat))
       if(SUCCESS!=mdlLevel_getCode (&levelCode,mdlLevelLibrary_getModelRef(),val.value.sLongFormat))
          levelCode=LEVEL_DEFAULT_LEVEL_CODE;
    pRowAdd = mdlListRow_create (enhanceListModel);
    mdlListModel_insertRow (enhanceListModel,pRowAdd,-1);
    pCell = mdlListRow_getCellAtIndex (pRowAdd, 0);
    if(SUCCESS!=mdlLevel_getName(levelNameOutput,MAX_LEVEL_NAME_LENGTH,mdlModelRef_getActive(),val.value.sLongFormat))
    mdlLevel_getName(levelNameOutput,MAX_LEVEL_NAME_LENGTH,mdlLevelLibrary_getModelRef(),val.value.sLongFormat);
    mdlCnv_convertUnicodeToMultibyte (levelNameOutput, -1,levelString, MAX_LEVEL_NAME_LENGTH);
    mdlListCell_setStringValue(pCell,levelString,TRUE);
    mdlListCell_setLongValue (pCell,levelCode);
    pCell = mdlListRow_getCellAtIndex (pRowAdd, 1);
    sprintf(levelString,"%lu",levelCode);
    mdlListCell_setStringValue(pCell,levelString,TRUE);
    }
    pListModel=mdlListModel_copy (enhanceListModel);
    mdlListModel_destroy (enhanceListModel, TRUE);
    }
    mdlDialog_comboBoxSetListModelP (dimP->dialogItemP->rawItemP, pListModel);
    break;
    }

  • Unicode

    Ray:
    
    char levelString [MAX_LEVEL_NAME_LENGTH];
    MSWChar levelNameOutput [MAX_LEVEL_NAME_LENGTH]; 
    mdlLevel_getName (levelNameOutput, MAX_LEVEL_NAME_LENGTH, mdlLevelLibrary_getModelRef (), val.value.sLongFormat);
    mdlCnv_convertUnicodeToMultibyte (levelNameOutput, -1, levelString, MAX_LEVEL_NAME_LENGTH);
    mdlListCell_setStringValue (pCell, levelString, TRUE);
    
    

    V8 mostly uses Unicode (MSWChar) for strings. Not all the old APIs have been converted, but pretty well everything that is new in V8 is Unicode. Moreso when you look at the MicroStationAPI.

    In this case, you don't need to convert the level name from Unicode to multibyte in order to set it as the ListCell's value. You can use the wide-character function to set the value directly …

    
    MSWChar levelNameOutput [MAX_LEVEL_NAME_LENGTH]; 
    mdlLevel_getName (levelNameOutput, MAX_LEVEL_NAME_LENGTH, mdlLevelLibrary_getModelRef (), val.value.sLongFormat);
    mdlListCell_setStringValueW (pCell, levelNameOutput, TRUE);
    
    

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • Jon,

    Yes, I saw that there is a unicode version to set the strings.  Any thoughts on how to sort out the levels read from a level lib as opposed to the master file?

  • Ray:

    Any thoughts on how to sort out the levels read from a level lib as opposed to the master file?

    Enumerate the level libraries first, then look in the active model. Store the name of the file that contains each level in your ListModel …

    
    LevelLibraryRefP   lib = mdlLevelLibrary_getFirst ();
    while (NULL != lib)
    {
    mdlLevelLibrary_getName (libName, …, lib);
    ray_extractLevels (lib);
    lib = mdlLevelLibrary_getNext (lib);
    }
    
    

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • One more thing, when I populate my new list model replacing the levelID with level codes I am losing my LEVELLIST_BOLD_USED attribute in my combo box, so that my used levels don't show up bold in the combo box.  How can I retain that attribute?

    Ray

  • as you build the list cell you can use the mdlListCell_setFontIndex function to set the font used to be FONT_INDEX_BOLD.

     

    HTH,

    mark anderson [Bentley]