/// <summary> /// Creates and idling task that will bind our own Synch to Central command to existing one. /// </summary> public static void CreateSynchToCentralOverride() { AppCommand.EnqueueTask(app => { try { var commandId = RevitCommandId.LookupCommandId("ID_FILE_SAVE_TO_MASTER"); var commandId2 = RevitCommandId.LookupCommandId("ID_FILE_SAVE_TO_MASTER_SHORTCUT"); if (commandId == null || commandId2 == null || !commandId2.CanHaveBinding || !commandId.CanHaveBinding) { return; } // (Konrad) We shouldn't be registering the same event handler more than once. It will throw an exception if we do. // It would also potentially cause the event to be fired multiple times. if (!AppCommand.IsSynchOverriden) { var binding = app.CreateAddInCommandBinding(commandId); binding.Executed += (sender, e) => OnSynchToCentral(sender, e, SynchType.Synch); AppCommand.IsSynchOverriden = true; } if (!AppCommand.IsSynchNowOverriden) { var binding2 = app.CreateAddInCommandBinding(commandId2); binding2.Executed += (sender, e) => OnSynchToCentral(sender, e, SynchType.SynchNow); AppCommand.IsSynchNowOverriden = true; } } catch (Exception e) { Log.AppendLog(LogMessageType.EXCEPTION, e.Message); } }); }
/// <summary> /// Replacement method for reloading latest which disables the DTM Tool. /// </summary> public static void OnReloadLatest(object sender, ExecutedEventArgs args) { // (Konrad) This will disable the DTM Tool when we are reloading latest. AppCommand.IsSynching = true; // (Konrad) Reloads Latest. AppCommand.EnqueueTask(app => { try { Log.AppendLog(LogMessageType.INFO, "Reloading Latest..."); var reloadOptions = new ReloadLatestOptions(); var doc = app.ActiveUIDocument.Document; doc.ReloadLatest(reloadOptions); if (!doc.HasAllChangesFromCentral()) { doc.ReloadLatest(reloadOptions); } } catch (Exception e) { Log.AppendLog(LogMessageType.EXCEPTION, e.Message); } }); // (Konrad) Turns the DTM Tool back on when reload is done. AppCommand.EnqueueTask(app => { AppCommand.IsSynching = false; }); }
/// <summary> /// /// </summary> public void LaunchWebsite() { AppCommand.EnqueueTask(app => { var doc = app.ActiveUIDocument.Document; var centralPath = FileInfoUtil.GetCentralFilePath(doc); if (string.IsNullOrWhiteSpace(centralPath)) { return; } if (MissionControlSetup.Projects.ContainsKey(centralPath)) { Process.Start(ServerUtilities.RestApiBaseUrl + "/#/projects/healthreport/" + MissionControlSetup.Projects[centralPath].Id); } }); }
/// <summary> /// /// </summary> public void LaunchWebsite() { AppCommand.EnqueueTask(app => { var doc = app.ActiveUIDocument.Document; var centralPath = FileInfoUtil.GetCentralFilePath(doc); if (string.IsNullOrEmpty(centralPath)) { return; } if (MissionControlSetup.Projects.ContainsKey(centralPath)) { Process.Start("http://missioncontrol.hok.com/#/projects/healthreport/" + MissionControlSetup.Projects[centralPath].Id); } }); }
/// <summary> /// Communicator Image can only be set when we are done loading the app. /// </summary> public static void SetCommunicatorImage() { // (Konrad) This needs to run after the doc is opened, because UI elements don't get created until then. AppCommand.EnqueueTask(app => { var dpid = new DockablePaneId(new Guid(Properties.Resources.CommunicatorGuid)); var dp = app.GetDockablePane(dpid); var assembly = Assembly.GetExecutingAssembly(); if (dp != null) { AppCommand.Instance.CommunicatorButton.LargeImage = ButtonUtil.LoadBitmapImage(assembly, "HOK.MissionControl", dp.IsShown() ? "communicatorOn_32x32.png" : "communicatorOff_32x32.png"); AppCommand.Instance.CommunicatorButton.ItemText = dp.IsShown() ? "Hide" + Environment.NewLine + "Communicator" : "Show" + Environment.NewLine + "Communicator"; } }); }
/// <summary> /// Creates an idling task that will bind our own Reload Latest command to existing one. /// </summary> public static void CreateReloadLatestOverride() { AppCommand.EnqueueTask(app => { try { var commandId = RevitCommandId.LookupCommandId("ID_WORKSETS_RELOAD_LATEST"); if (commandId == null || !commandId.CanHaveBinding) { return; } var binding = app.CreateAddInCommandBinding(commandId); binding.Executed += OnReloadLatest; } catch (Exception e) { Log.AppendLog(LogMessageType.EXCEPTION, e.Message); } }); }
/// <summary> /// /// </summary> /// <param name="text"></param> public void LaunchCommand(string text) { var commandName = string.Empty; switch (text) { case "Links Manager": commandName = "CustomCtrl_%CustomCtrl_% HOK %Mission Control%LinksManager_Command"; break; case "Groups Manager": commandName = "CustomCtrl_%CustomCtrl_% HOK %Mission Control%GroupManager_Command"; break; case "Styles Manager": commandName = "CustomCtrl_%CustomCtrl_% HOK %Mission Control%StylesManager_Command"; break; } if (string.IsNullOrEmpty(commandName)) { return; } var addinId = RevitCommandId.LookupCommandId(commandName); if (addinId == null) { return; } AppCommand.EnqueueTask(app => { app.PostCommand(addinId); }); }
/// <summary> /// Registers availble configuration based on Central Model path match. /// </summary> private static void ApplyConfiguration(Document doc) { try { var centralPath = FileInfoUtil.GetCentralFilePath(doc); var config = MissionControlSetup.Configurations[centralPath]; var launchSockets = false; foreach (var updater in config.Updaters) { if (!updater.IsUpdaterOn) { continue; } if (string.Equals(updater.UpdaterId, AppCommand.Instance.DoorUpdaterInstance.UpdaterGuid.ToString(), StringComparison.OrdinalIgnoreCase)) { // (Konrad) We need to register updaters from within Revit context. // That's why we are running this in the Idling Event. AppCommand.EnqueueTask(app => { AppCommand.Instance.DoorUpdaterInstance.Register(doc, updater); }); } else if (string.Equals(updater.UpdaterId, AppCommand.Instance.DtmUpdaterInstance.UpdaterGuid.ToString(), StringComparison.OrdinalIgnoreCase)) { ProcessTriggerRecords(centralPath); AppCommand.EnqueueTask(app => { AppCommand.Instance.DtmUpdaterInstance.Register(doc, updater); }); DTMTool.DtmSynchOverrides.CreateReloadLatestOverride(); DTMTool.DtmSynchOverrides.CreateSynchToCentralOverride(); } else if (string.Equals(updater.UpdaterId, Properties.Resources.LinkUnloadTrackerGuid, StringComparison.OrdinalIgnoreCase)) { AppCommand.EnqueueTask(app => { LinkUnloadMonitor.LinkUnloadMonitor.CreateLinkUnloadOverride(app); }); } else if (string.Equals(updater.UpdaterId, Properties.Resources.SheetsTrackerGuid, StringComparison.OrdinalIgnoreCase)) { ProcessSheets(ActionType.CheckIn, doc, centralPath); launchSockets = true; } else if (string.Equals(updater.UpdaterId, Properties.Resources.HealthReportTrackerGuid, StringComparison.OrdinalIgnoreCase)) { // (Konrad) These are read-only methods so they don't need to run in Revit context. ProcessModels(ActionType.CheckIn, doc, centralPath); ProcessWorksets(ActionType.CheckIn, doc, centralPath); #if RELEASE2015 || RELEASE2016 || RELEASE2017 // (Konrad) We are not going to process warnings here. #else ProcessWarnings(ActionType.CheckIn, doc, centralPath); #endif ProcessFamilies(centralPath); ProcessStyle(doc, centralPath); ProcessLinks(doc, centralPath); ProcessViews(doc, centralPath); ProcessGroups(doc, centralPath); launchSockets = true; } } // (Konrad) This tool will reset Shared Parameters Location to one specified in Mission Control if (config.GetType().GetProperty("sharedParamMonitor") != null && config.SharedParamMonitor.IsMonitorOn) { if (File.Exists(config.SharedParamMonitor.FilePath)) { doc.Application.SharedParametersFilename = config.SharedParamMonitor.FilePath; } else { Log.AppendLog(LogMessageType.ERROR, "Failed to reset Shared Parameter location. Could not find file specified."); } } if (launchSockets) { // (Konrad) in order not to become out of synch with the database we need a way // to communicate live updates from the database to task assistant/communicator var socket = new MissionControlSocket(doc); socket.Start(); AppCommand.Socket = socket; } // Publish user/machine info to be used by Zombie var userInfo = new UserItem { User = Environment.UserName.ToLower(), Machine = Environment.MachineName }; if (!ServerUtilities.Post(userInfo, "users/add", out ResponseCreated unused1)) { Log.AppendLog(LogMessageType.ERROR, "Failed to publish User/Machine Data."); } } catch (Exception ex) { Log.AppendLog(LogMessageType.EXCEPTION, ex.Message); } }
/// <summary> /// Ovveride method for when user synchs to central. /// The goal here is to disable the DTM Tool and prevent pop-ups while synching. /// </summary> public static void OnSynchToCentral(object sender, ExecutedEventArgs args, SynchType synchType) { // (Konrad) This will disable the DTM Tool when we are synching to central. AppCommand.IsSynching = true; RevitCommandId commandId; switch (synchType) { case SynchType.Synch: commandId = RevitCommandId.LookupCommandId("ID_FILE_SAVE_TO_MASTER"); break; case SynchType.SynchNow: commandId = RevitCommandId.LookupCommandId("ID_FILE_SAVE_TO_MASTER_SHORTCUT"); break; default: throw new ArgumentOutOfRangeException(nameof(synchType), synchType, null); } if (commandId == null || !commandId.CanHaveBinding) { return; } AppCommand.EnqueueTask(app => { try { app.RemoveAddInCommandBinding(commandId); switch (synchType) { case SynchType.Synch: AppCommand.IsSynchOverriden = false; break; case SynchType.SynchNow: AppCommand.IsSynchNowOverriden = false; break; default: throw new ArgumentOutOfRangeException(nameof(synchType), synchType, null); } } catch (Exception e) { Log.AppendLog(LogMessageType.EXCEPTION, e.Message); } }); AppCommand.EnqueueTask(app => { // (Konrad) We can now post the same Command we were overriding since the override is OFF. app.PostCommand(commandId); // (Konrad) Once the command executes this will turn the override back ON. AppCommand.IsSynching = false; var doc = app.ActiveUIDocument.Document; var centralPath = FileInfoUtil.GetCentralFilePath(doc); if (string.IsNullOrEmpty(centralPath)) { return; } // (Konrad) Let's turn the synch command override back on. var config = MissionControlSetup.Configurations[centralPath]; foreach (var updater in config.Updaters) { if (!updater.IsUpdaterOn) { continue; } if (string.Equals(updater.UpdaterId.ToLower(), AppCommand.Instance.DtmUpdaterInstance.UpdaterGuid.ToString().ToLower(), StringComparison.Ordinal)) { CreateSynchToCentralOverride(); } } }); }