TBC Macros and Extensions

 View Only
Expand all | Collapse all

use a macro to move a sheetset into another planset

  • 1.  use a macro to move a sheetset into another planset

    Posted 10-08-2024 22:45

    I'm trying to reorganize some sheetsets into separate plansets.

    I don't understand why this is not an option out of the box. Plansets are basically just a folder with no dimensions or the like. So, it should be less difficult than moving sheets to a different sheetset, which is surprisingly possible out of the box.

    I've investigated so far that a sheetset resides within a planset and the planset observes the sheetset. And that's it, I can't see any other connections or dependencies.

    So, it should just be a matter of reassigning the observer like this

    self.currentProject.Concordance.AddObserver(ss.SerialNumber, targetplanset.SerialNumber)
    self.currentProject.Concordance.RemoveObserver(ss.SerialNumber, sourceplanset.SerialNumber)
    

    With the ViewProjectData macro I can confirm that it looks as it should in the internal project tree, but it's not being reflected properly in the project explorer.

    Even if I encapsulate it in the usual

    with TransactMethodCall(self.currentProject.TransactionCollector) as failGuard:
         failGuard.Commit()

    it does work once and after that any further changes won't update the project explorer, as if something got broken.

    I don't really want it to be reversible via Undo. Any idea how to make this work. Main issue is the project explorer.



    ------------------------------
    Ronny Schneider
    ------------------------------


  • 2.  RE: use a macro to move a sheetset into another planset

    Posted 10-14-2024 10:15
    Edited by Bryce Haire 10-14-2024 10:19

    Hi Ronny,

    Try using the static ExplorerData.TheExplorer (namespace Trimble.Vce.UI.ProjectExplorer2) and see if calling "UpdateData" and see if it helps (haven't verified myself fyi). 

    I wouldn't necessarily this is a common workflow you are doing (so not totally surprised it is acting funny) but it may address your Project Explorer issue. 



    ------------------------------
    Bryce Haire
    ------------------------------



  • 3.  RE: use a macro to move a sheetset into another planset

    Posted 10-14-2024 15:37

    Thanks Bryce,

    I had found that one meanwhile, but it doesn't help. I don't know what it is doing exactly, but it's not updating the project explorer based on the project tree/content.

    I also tried InvalidateUI with the planset node which supposedly redraws the UI, but no luck with that one either. And I'm sure I have the correct one since I can see the Items list populating when I manually expand the explorer tree.

    And I'm pretty sure that the rest I'm doing is correct, because after running my macro, saving the project and loading it again the project explorer looks correct and the sheetset is inheriting linework correctly from the new planset. So, it's really just a matter of triggering that full explorer rebuild correctly.

    What is SheetSet.ChangeSheetParent doing internally? I'm basically trying to do the same on planset level, which should be an option out of the box anyway. There should be a PlanSetSheetView.ChangeSheetSetParent.



    ------------------------------
    Ronny Schneider
    ------------------------------



  • 4.  RE: use a macro to move a sheetset into another planset

    Posted 10-14-2024 15:52
    Edited by Bryce Haire 10-14-2024 15:53

    Unfortunately, it has a private class ModifyContainedEntityList that you do not have access to. 

    The ChangeParentMode seems like it fires the EntityAdded (Trimble.Sdk.ModelEvents - EventRaiser.RaiseEntityAdded) event.

    While not ideal, maybe try firing that (or RaiseEntityEdited) and see if that works. 

    /// <summary>
            /// Method to add or remove a sheet in this sheetSet
            /// </summary>
            /// <param name="Add">If true, add sheet to this sheetset, else remove</param>
            /// <param name="sheet">The sheet to "move"</param>
            public void ChangeSheetParent(bool Add, BasicSheet sheet)
            {
                ModifyContainedEntityList NewCmd = null;
                if (Add && !this.Contains(sheet.SerialNumber))
                {
                    NewCmd = new ModifyContainedEntityList(ModifyContainedEntityList.Mode.Add, SerialNumber, sheet.SerialNumber, 0);
                    NewCmd.ChangeParentMode = true;
                    MyTransactionCollector.Do(NewCmd);
                    ForceDirty(MyTransactionCollector);
                }
                else if (!Add && this.Contains(sheet.SerialNumber))
                {
                    NewCmd = new ModifyContainedEntityList(ModifyContainedEntityList.Mode.Remove, SerialNumber, sheet.SerialNumber, 0);
                    NewCmd.ChangeParentMode = true;
                    MyTransactionCollector.Do(NewCmd);
                    ForceDirty(MyTransactionCollector);
                }
            }



    ------------------------------
    Bryce Haire
    ------------------------------



  • 5.  RE: use a macro to move a sheetset into another planset

    Posted 10-17-2024 00:09

    I believe I figured it out.

    ExplorerData.TheExplorer.UpdateData() only redraws the UI based on an Itemslist which needs to be updated first.

    Not sure if there is a more elegant way. So far this looks like it's doing what is necessary to keep the ProjectExplorer consistent after changing the database with AddObserver/RemoveObserver as shown above.

                    te = ExplorerData.TheExplorer
                    
                    ## find the plansetcollection - node
                    for i in te.Items.AllItems:
                        if isinstance(i, PlanSetCollection):
                            pscn = i
    
                    pscn.Expanded = True # must expand it, otherwise the allitems list won't be populated
                    
                    tt = [] # need temp list since we may run into an error while removing data from a live enumerator
                    for i in pscn.Items.AllItems:
                        if isinstance(i, PlanSetNode):
                            tt.Add(i)
                    
                    # now call removeitem on all plansetnodes - that basically empties the planset node in the project explorer
                    for i in tt:
                        pscn.RemoveItem(i)
                    
                    # trigger re-populate of all child items from plansetnode level
                    # this will recreate the items list based on the project tree database we altered with addobserver/removeobserver
    
                    pscn.Populate()
    
                    # re-expand the tree
                    for i in pscn.Items.AllItems:
                        if isinstance(i, PlanSetNode):
                            i.Expanded = True
    
                    # redraw the ui
                    te.UpdateData()
    


    ------------------------------
    Ronny Schneider
    ------------------------------



  • 6.  RE: use a macro to move a sheetset into another planset

    Posted 01-30-2025 15:51

    Unfortunately, I need to come back to this.

    Is there another way to change an objects container, beside what I'm currently doing?

    oldbimentity.SetSite(newbimsite)
    self.currentProject.Concordance.AddObserver(oldbimentity.SerialNumber, newbimsite.SerialNumber)
    self.currentProject.Concordance.RemoveObserver(oldbimentity.SerialNumber, oldbimsite.SerialNumber) #RemoveObserver(uint target, uint source) source is the observer
    

    The drawback with this approach is that Undo/Redo doesn't properly comprehend what has happened. I can't encapsulate it in

    UIEvents.RaiseBeforeDataProcessing(self, UIEventArgs())
    self.currentProject.TransactionManager.AddBeginMark(CommandGranularity.Command, self.Caption)
    
    
    UIEvents.RaiseAfterDataProcessing(self, UIEventArgs())
    self.currentProject.TransactionManager.AddEndMark(CommandGranularity.Command)

    That immediately throws an error when I try to Undo. So, I need to refrain from triggering those events and hence can't Undo the AddObserver/RemoveObserver action.

    But that poses a problem with earlier events in the Undo chain, because now the entity is not where an older Undo thinks it is, and that Undo will fail.

    The only other option I currently see is to use the sledgehammer method and clear the Undo stack after my "Observer" calls.

    self.currentProject.TransactionManager.ResetUndoRedoStack()


    ------------------------------
    Ronny Schneider
    ------------------------------



  • 7.  RE: use a macro to move a sheetset into another planset

    Posted 02-05-2025 13:23

    Hi Ronny,

    After swapping the observers, can you try adding (maybe for both snapins (new/old))

    self.currentProject.Concordance.ObjectChangedNotification(newbimsite.SerialNumber)

    This may trigger the concordance to recalculate, and clear the undo issue you were experiencing (because the SnapIn accepts the site change). 

    This is maybe a shot in the dark, as I am not sure that the SDK and/or BIM objects are setup for clients to manually swap containers of the snap-ins themselves. 

    Let me know if this helps any :P 



    ------------------------------
    Bryce Haire
    ------------------------------