[CONNECT C++] How to set visibility on tags within a placed cell

I have installed:

MicroStation CONNECT Edition
10.15.0.74

MicroStation CONNECT Edition SDK
10.15.00.076

I have a dgn file with several cells, each contain numerous tags whose display is off that I need to turn their display on.  This can readily be done manually via the EDIT TAGS command but I need to do it programatically using the native C++ API.  Note: I was able to change the tag values on these tags but not their visibility.

I have pasted my example code below.   In my callback function eehTag.ReplaceInModel() always returns SUCCESS.  However the tag are still not visible.

Any assistance would be appreciated. 

Thanks,

John M.

Example Code

int ModifyTagsVisibilityScanCallback (ElementRefP elemRef, void* userData, ScanCriteriaP scP)
    {
    if (elementRef_hasDependents (elemRef))
        {
        wprintf(L"ModifyTagsVisibilityScanCallback() element has dependents\n");

        for (DependentElemRef dep = elementRef_getFirstDependent (elemRef); NULL != dep; dep = elementDependent_getNext (dep))
            {
            ElementRefP depRef = elementDependent_getElemRef (dep);

            if (MSElementTypes::ATTRIBUTE_ELM == elementRef_getElemType (depRef))
                {
                int status = SUCCESS;

                EditElementHandle eehTag;
                eehTag.FindByID (elementRef_getElemID (depRef), scP->GetModelRef());

                // Set the tag visiblility to visible.
                bool hide = false;  
                bool isSharedCell = false;  

                if (SUCCESS == TagElementHandler::SetVisibility (eehTag, hide, isSharedCell))
                    {
                    if (SUCCESS != eehTag.ReplaceInModel (depRef))
                        wprintf (L"ModifyTagsVisibilityScanCallback() Error ReplaceInModel. status = %d\n", status);
                    }
                }
            }              
        }

    return 0;
    }
      

int generate_updateBorderCellTagVisibility (WCharCP cellName)
    {
    int status = SUCCESS;

    UShort typeMaskArray[8] = {0};
    typeMaskArray[0] = TMSK0_CELL_HEADER;

    ScanCriteriaP sc = mdlScanCriteria_create();

    // Scan for all cells of the requested cellName in the active model
    mdlScanCriteria_setModel (sc, mdlModelRef_getActive());
    mdlScanCriteria_setReturnType (sc, MSSCANCRIT_ITERATE_ELMREF, FALSE, TRUE);
    mdlScanCriteria_setElementTypeTest (sc, typeMaskArray,sizeof (typeMaskArray));
    mdlScanCriteria_setCellNameTest (sc, cellName);
    mdlScanCriteria_setElemRefCallback (sc, ModifyTagsVisibilityScanCallback, NULL);
    mdlScanCriteria_scan (sc, NULL, NULL, NULL);

    mdlScanCriteria_free (sc);
    
    return status;    
    }   

Parents
  • I was able to change the tag values on these tags but not their visibility

    Tags are elements and inherit their ability to be visible.  A tag definition (DgnTagDefinition: see DgnPlatform.r.h) additionally has a displayable property.  In addition to TagElementHandler::SetVisibility() we also have ITagCreateData::SetTagVisibility().  

    Your goal is to toggle bit DgnTagDefinition::propsMask::TAG_PROP_DISPOFF.  It's not clear from the MicroStationAPI documentation if that is the intention of TagElementHandler::SetVisibility() or ITagCreateData::SetTagVisibility()

    When I select the cell for ANALYZE ELEMENT the tree view does not list any tag elements

    When you attach a tag to an element, you don't modify the element.  The tag is a separate entity.  The tag is associated to its host using the host's element ID.  You can see that if you use command Analyze Element to examine a tag element: see this article.

     
    Regards, Jon Summers
    LA Solutions

  • Hey Jon,

    SetTagVisibility is a member of is not a member of ITagCreateData, not TagElementHandler.

    --JohnM.

  • Despite the name, from looking at the implementation of TagElementHandler::SetVisibility, it's definitely not doing what you want.

    * This method probably shouldn't even be published, it's just confusing. It's value would be if you were writing your own "place cell" tool as it's purpose is to ensure the newly extract/associated tag elements have the correct visibility and isn't for changing the visibility of existing tag elements.

    It appears that the "expected" way to change visibility is by calling TagElementHandler::Create with ITagCreateData where you've called SetTagVisibility...I don't see a more convenient method if visibility is the only thing you want to change. The "edit tags" command does the same thing to change visibility as it does to edit values...i.e. extract/create.

    Not sure if you could just get away with doing this:

    eehTag.GetElementP()->dhdr.props.b.invisible = false;

    ^ This will definitely make the tags display, they might hide themselves by default if they are edited since ATTR_FLAG_HIDEINSTANCE isn't being cleared...you'd have to experiment. Slight smile

    -B



  • Hey Brien,

    Thanks for the suggestion.  See corrected code below.  I managed to get it to work using mdlElmdscr_setVisible().  Sure would be nice if a new public function TagElementHandler::SetVisibility() were added to set this flag so that we wouldn't have to use the MSElementDesc API.  Right now I'm just happy it works.   Even better, any CRUD operation that can be performed using the old school MSElementDesc API should also be available in the new EditElementHandle/*Handler API.

    Thanks,
    John M.

    Corrected Code

    int ModifyTagsVisibilityScanCallback (ElementRefP elemRef, void* userData, ScanCriteriaP scP)
        {
        if (elementRef_hasDependents (elemRef))
            {
            wprintf(L"ModifyTagsVisibilityScanCallback() element has dependents\n");
    
            for (DependentElemRef dep = elementRef_getFirstDependent (elemRef); NULL != dep; dep = elementDependent_getNext (dep))
                {
                ElementRefP depRef = elementDependent_getElemRef (dep);
    
                if (MSElementTypes::ATTRIBUTE_ELM == elementRef_getElemType (depRef))
                    {
                    ElementId elementId = elementRef_getElemID (depRef);
    
                    MSElementDescrP edP = NULL;
                    mdlAssoc_getElementDescr (&edP, NULL, elementId, scP->GetModelRef(), false);
    
                    mdlElmdscr_setVisible (edP, TRUE);  
                    mdlElmdscr_rewrite (edP, NULL, mdlElmdscr_getFilePos (edP));
                    mdlElmdscr_freeAll (&edP);              
                    }
                }              
            }
    
        return 0;
        }

  • Element Visibility

    eehTag.GetElementP()->dhdr.props.b.invisible = false;
    I managed to get it to work using mdlElmdscr_setVisible()

    Those calls are doing the same thing, which is to set the inherited MSElement flag.

    TAG_PROP_DISPOFF

    As I mentioned above, a tag definition has another flag DgnTagDefinition::propsMask::TAG_PROP_DISPOFF.  That tells a tag that it should not display itself.  I don't know how or if that flag interacts with the MSElement flag.

    ATTR_FLAG_HIDEINSTANCE

    they might hide themselves by default if they are edited since ATTR_FLAG_HIDEINSTANCE isn't being cleared

    I don't see ATTR_FLAG_HIDEINSTANCE in the SDK header files.

     
    Regards, Jon Summers
    LA Solutions

  • As I mentioned above, a tag definition has another flag DgnTagDefinition::propsMask::TAG_PROP_DISPOFF.  That tells a tag that it should not display itself.  I don't know how or if that flag interacts with the MSElement flag.

    TAG_PROP_DISPOFF controls the default visibility of the tag elements created for a tag set when you use the "attach tags" tool. The element flag that you can change with the "edit tags" tool overrides the default visibility from the tag set definition for individual elements.

    I don't see ATTR_FLAG_HIDEINSTANCE in the SDK header files.

    I should have been less specific. :) There are various flags that are part of tag element data, and one is related to visibility of un-associated tags. When the rubber meets the road, it's dhdr.props.b.invisible that ultimately controls whether the tag displays or not, and the internal element data is managed by the "tag" api methods/functions.

    -B



Reply
  • As I mentioned above, a tag definition has another flag DgnTagDefinition::propsMask::TAG_PROP_DISPOFF.  That tells a tag that it should not display itself.  I don't know how or if that flag interacts with the MSElement flag.

    TAG_PROP_DISPOFF controls the default visibility of the tag elements created for a tag set when you use the "attach tags" tool. The element flag that you can change with the "edit tags" tool overrides the default visibility from the tag set definition for individual elements.

    I don't see ATTR_FLAG_HIDEINSTANCE in the SDK header files.

    I should have been less specific. :) There are various flags that are part of tag element data, and one is related to visibility of un-associated tags. When the rubber meets the road, it's dhdr.props.b.invisible that ultimately controls whether the tag displays or not, and the internal element data is managed by the "tag" api methods/functions.

    -B



Children
  • I also verified from the command Edit Tags that the Display is column is checked for all of the tags for which I set the invisible property to false:

    Since the invisible property is generic to all elements perhaps a better recommendation would be to add a new function:

            EditElementHandle:SetVisibility (EditElementHandleR telement, bool hide); 

  • Since the invisible property is generic to all elements perhaps a better recommendation would be to add a new function:

    It's not though, not all elements are displayable...

    There's nothing wrong with setting dhdr.props.b.invisible directly for something like this that should be rarely needed. You can always create your own library of utility methods you find useful. After all, you need something today, and you probably wouldn't revisit this code in 6 months or whenever a new version released with a new method...or would you want to require that version in order to load your application.

    void makeVisibile(EditElementHandleR eeh) { if (eeh.GetElementCP()->ehdr.isGraphics) eeh.GetElementP()->dhdr.props.b.invisible = false; };

    * note: isGraphics check is redundant if you've already checked that it's a tag element...

    -B