/// <summary> /// Repeatedly check database status and raise /// external event when updates are pending. /// Relinquish control and wait for timeout /// period between each attempt. Run in a /// separate thread. /// </summary> static void CheckForPendingDatabaseChanges() { while (null != _event) { ++_nLoopCount; Debug.Assert(null != _event, "expected non-null external event"); if (_event.IsPending) { Util.Log(string.Format( "CheckForPendingDatabaseChanges loop {0} - " + "database update event is pending", _nLoopCount)); } else { using (JtTimer pt = new JtTimer( "CheckForPendingDatabaseChanges")) { ++_nCheckCount; Util.Log(string.Format( "CheckForPendingDatabaseChanges loop {0} - " + "check for changes {1}", _nLoopCount, _nCheckCount)); RoomEditorDb rdb = new RoomEditorDb(); if (rdb.LastSequenceNumberChanged( DbUpdater.LastSequence)) { _event.Raise(); ++_nUpdatesRequested; Util.Log(string.Format( "database update pending event raised {0} times", _nUpdatesRequested)); #region Obsolete attempts that failed // Move the mouse in case the user does // not. Otherwise, it may take a while // before Revit forwards the event Raise // to the event handler Execute method. // Just moving the mouse is not enough: //System.Drawing.Point p = Cursor.Position; //Cursor.Position = new System.Drawing // .Point( p.X + 1, p.Y ); //Cursor.Position = p; // This did not work either: //[DllImport( "user32.dll" )] //static extern IntPtr SetFocus( // IntPtr hwnd ); //IWin32Window revit_window // = new JtWindowHandle( // ComponentManager.ApplicationWindow ); //IntPtr hwnd = SetFocus( revit_window.Handle ); //IntPtr hwnd2 = SetFocus( hwnd ); //Debug.Print( "set to rvt {0} --> {1} --> {2}", // revit_window.Handle, hwnd, hwnd2 ); // Try SendKeys? #endregion // Obsolete attempts that failed // Set focus to Revit for a moment. // Otherwise, it may take a while before // Revit forwards the event Raise to the // event handler Execute method. IntPtr hBefore = GetForegroundWindow(); SetForegroundWindow( ComponentManager.ApplicationWindow); SetForegroundWindow(hBefore); } } } // Wait a moment and relinquish control before // next check for pending database updates. Thread.Sleep(_timeout); } }
/// <summary> /// Apply all current cloud database /// changes to the BIM. /// </summary> public void UpdateBim() { Util.Log("UpdateBim begin"); using (JtTimer pt = new JtTimer("UpdateBim")) { Document doc = _uiapp.ActiveUIDocument.Document; // Retrieve all room unique ids in model: FilteredElementCollector rooms = new FilteredElementCollector(doc) .OfClass(typeof(SpatialElement)) .OfCategory(BuiltInCategory.OST_Rooms); IEnumerable <string> roomUniqueIds = rooms.Select <Element, string>( e => e.UniqueId); // Convert to a dictionary for faster lookup: _roomUniqueIdDict = new Dictionary <string, int>( roomUniqueIds.Count()); foreach (string s in roomUniqueIds) { _roomUniqueIdDict.Add(s, 1); } //string ids = "?keys=[%22" + string.Join( // "%22,%22", roomUniqueIds ) + "%22]"; // Retrieve all furniture transformations // after the last sequence number: CouchDatabase db = new RoomEditorDb().Db; ChangeOptions opt = new ChangeOptions(); opt.IncludeDocs = true; opt.Since = LastSequence; opt.View = "roomedit/map_room_to_furniture"; // I tried to add a filter to this view, but // that is apparently not supported by the // CouchDB or DreamSeat GetChanges functionality. //+ ids; // failed attempt to filter view by room id keys // Specify filter function defined in // design document to get updates //opt.Filter = CouchChanges <DbFurniture> changes = db.GetChanges <DbFurniture>(opt); CouchChangeResult <DbFurniture>[] results = changes.Results; foreach (CouchChangeResult <DbFurniture> result in results) { UpdateBimFurniture(result.Doc); LastSequence = result.Sequence; } } Util.Log("UpdateBim end"); }