Revit2011 API standout feature – being Idle

by Guy Robinson 19. April 2010 13:36

To be honest I’m loathed to single out a single standout feature from the new API’s. There is no doubt Updaters are going to be widely use. They plug a major gap in the API’s capabilities, the Updater API is well designed and are fast. However, there is a single API that does standout and in my opinion allows developers to begin the process of seamlessly integrating Revit into users BIM workflows unlike anything that has been possible before. And that API is the Application Idling event.

What happens is every time a user does nothing ;-) Revit will fire an application idling event. API developers can subscribe to this and do some work. The developer needs to make sure they don’t spend too much time in the handler and provide visual feedback on what they’re doing or the user experience will be significantly degraded and potential confusion. 

There are a number of patterns possible with the Idling event and I’ll cover a simple one initially. Essentially this pattern replicates what updaters can do but in a more asynchronous manner. Although in the example command I’m not doing anything with the data. It uses an Idling event in conjunction with a DocumentChanged event to queue elements to be processed as required. The processing will only happen when Revit is idle.Here’s a screen shot:

Idle1

The command opens a window that stays on top, that can be moved but not closed. The count shows the number of items in the queue to be processed and the status shows whether Revit is working or idling (orange working, green idle). I’ve intentionally slowed things down to try and show you how and when the idle event fires and the instances in the queue are processed. Create a number of elements in succession (like walls without chaining) and then double escape and watch the queue count and status update. Pretty damn cool!!

The essential class is the DataService singleton class . It’s this class I use to wire up the Idling and DocumentChanged events and generate the queue of ChangedIdTick instances to process. Here’s the event handlers for the Revit Idling and DocumentChanged events:

/// <summary>
/// Documents changed event handler.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="Autodesk.Revit.DB.Events.DocumentChangedEventArgs"/> instance containing the event data.</param>
public void DocumentChanged(object sender, DocumentChangedEventArgs e)
{
    var activeDocument = e.GetDocument();
    // this allows us to reference the document by name rather than storing documents in the queue
    if (!_docTable.ContainsKey(activeDocument.Title)) _docTable.Add(activeDocument.Title, activeDocument);
 
    // now add a tick to the queue
    _queue.Enqueue(new ChangedIdTick(activeDocument.Title, e.GetAddedElementIds(), e.GetModifiedElementIds(), e.GetDeletedElementIds()));
}
 
/// <summary>
/// Applications idling event handler.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="Autodesk.Revit.UI.Events.IdlingEventArgs"/> instance containing the event data.</param>
public void ApplicationIdling(object sender, IdlingEventArgs e)
{
    if (_queue.Count != 0)
    {
        // if the queue has some ticks get one and sleep for 1/2 second
        var tick = _queue.Dequeue();
        Thread.Sleep(500);
    }
    //set the count rather than expose the queue to the viewmodel
    Count = _queue.Count;
    // now raise the event on the viewmodel
    OnRevitWasIdle(EventArgs.Empty);
}

And then the DataViewModel class provides the bridge between the revit dataservice and the WPF window. It subscribes to the DataServices’s RevitWasIdle event which the dataservice fires when it’s completed handling the Revit Idle event. The DataViewModel then updates the UI accordingly via databinding. If there are other aspect you’d like me to describe feel free to comment. I’ve tried to comment the code appropriately. Here’s the DataViewModel’s handler for the RevitWasIdle event.

/// <summary>
/// idle handler for dataservice.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="args">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void RevitWasIdleHandler(object sender, EventArgs args)
{
    IsIdle = true;
    Count = _revitDataService.Count.ToString();
    // using a dispatch timer to leave the idling radio button 
    // on for a 1 second
    // leave IsIdle on for 1 second if it's not already running
    if (!_dispatcherTimer.IsEnabled) _dispatcherTimer.Start();
}

Maybe you don’t find this Idle exciting. But you might (should) when I post the next pattern…

Exciting times!!!

Code in the usual place. Note it’s a VS2010 project so if you’re on 2008 delete the .sln and open the .csproj directly, and you’ll need to update the path in the addin or use the AddInManager from the SDK to use the binary.

Comments are closed

About the Author

A .NET software Developer providing custom applications and commands for architecture firms exclusively working with Autodesk Revit and integration with any associated applications. All from a little place north of Whitianga, New Zealand.

Page List

Disclaimer

I'm self employed so the opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway☺

© Copyright2008

Creative Commons License
Blog content is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.

With the following exception. All code snippets, application and libraries are licensed under a a Apache License Version 2.0

Autodesk Revit®

Autodesk: Revit is a product that is wholly owned by Autodesk. Any reference to Revit,Revit API, Revit Architecture, Revit MEP or Revit Structure on this site is made acknowledging this ownership. Refer to Autodesk's own web site and product pages for specific trademark and copyright information. Autodesk represents a great many products and every attempt will be made to respect their ownership whenever one of these other products is mentioned on this site.