diff options
author | Anže Vodovnik <anvod@microsoft.com> | 2019-07-29 12:56:40 +0300 |
---|---|---|
committer | Anže Vodovnik <anvod@microsoft.com> | 2019-07-29 21:18:08 +0300 |
commit | d7d1bc4f921be18f7848a95c19a28eca35a3cb8a (patch) | |
tree | 4f214272f4f15dc6b659396adf1fded2ac57feb9 | |
parent | 5a8dda4e6daabe1182f28562b0ae894a137a24f4 (diff) |
Use the new editor's command target when invoked from outside the editor.pr-anvod-formatnavigatefix
If commands were invoked outside the editor surface (i.e. from the Navigate
To widget), they would have focus set to that UI element and we would
never walk through the hierarchy in a way that would get us to the editor.
Now, if the walk-through fails, we simply try and get the custom command
target implemented by the new editor, and see if it can handle the command.
Also, we replicate the same behavior that happens across the rest of the
dispatching, which is that we invoke the Activating and Activated events.
I also replaced the usage of DateTime.Now with a Stopwatch as it's much
more precise.
Fixes VSTS https://devdiv.visualstudio.com/DevDiv/_workitems/edit/945987
Fixes VSTS https://devdiv.visualstudio.com/DevDiv/_workitems/edit/933997
-rw-r--r-- | main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs | 68 |
1 files changed, 59 insertions, 9 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs index 326e5a8299..f558ae264d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs @@ -1567,22 +1567,24 @@ namespace MonoDevelop.Components.Commands if (cmd.CommandArray) { handlers.Add (delegate { OnCommandActivating (commandId, info, dataItem, localTarget, source); - var t = DateTime.Now; + var t = Stopwatch.StartNew (); try { chi.Run (localTarget, cmd, dataItem); } finally { - OnCommandActivated (commandId, info, dataItem, localTarget, source, DateTime.Now - t); + t.Stop (); + OnCommandActivated (commandId, info, dataItem, localTarget, source, t.Elapsed); } }); } else { handlers.Add (delegate { OnCommandActivating (commandId, info, dataItem, localTarget, source); - var t = DateTime.Now; + var t = Stopwatch.StartNew (); try { chi.Run (localTarget, cmd); } finally { - OnCommandActivated (commandId, info, dataItem, localTarget, source, DateTime.Now - t); + t.Stop (); + OnCommandActivated (commandId, info, dataItem, localTarget, source, t.Elapsed); } }); } @@ -1603,7 +1605,40 @@ namespace MonoDevelop.Components.Commands UpdateToolbars (); return true; } - + + + // There is a special case, where some commands get called when we are running in the new editor. For + // example, if the user would be focused on a node in Solution Explorer and press Ctrl + I. Our walk + // across the controls wouldn't ever land us on the new editor itself, which is a command target. In + // those instances, we want to try and get that target and see if we can actually run the command in + // the new editor. If not, we'll revert to the old way. This is the same problem (and solution) + // that we use in <see cref="DefaultUpdateCommandInfo"/>. + if (IdeApp.Workbench?.ActiveDocument?.GetContent<ICustomCommandTarget> () is ICustomCommandTarget customCommandTarget) { + var updater = customCommandTarget.GetCommandUpdater (commandId); + var handler = customCommandTarget.GetCommandHandler (commandId); + + if(updater != null) { + updater?.Run (cmdTarget, info); + info.CancelAsyncUpdate (); + } + + if (info.Enabled && handler != null) { + var stopwatch = Stopwatch.StartNew (); + OnCommandActivating (commandId, info, dataItem, cmdTarget, source); + try { + handler.Run (cmdTarget, CurrentCommand); + return true; + } catch (Exception ex) { + // if we got here, something went wrong + LoggingService.LogInternalError (ex); + return false; + } finally { + stopwatch.Stop (); + OnCommandActivated (commandId, info, dataItem, cmdTarget, source, stopwatch.Elapsed); + } + } + } + if (DefaultDispatchCommand (cmd, info, dataItem, cmdTarget, source)) { UpdateToolbars (); return true; @@ -1639,11 +1674,12 @@ namespace MonoDevelop.Components.Commands } OnCommandActivating (cmd.Id, info, dataItem, target, source); - var t = DateTime.Now; + var t = Stopwatch.StartNew (); try { cmd.DefaultHandler.InternalRun (dataItem); } finally { - OnCommandActivated (cmd.Id, info, dataItem, target, source, DateTime.Now - t); + t.Stop (); + OnCommandActivated (cmd.Id, info, dataItem, target, source, t.Elapsed); } return true; } @@ -1825,9 +1861,23 @@ namespace MonoDevelop.Components.Commands info.ArrayInfo = new CommandArrayInfo (info); if (IsEnabled) cmd.DefaultHandler.InternalUpdate (info.ArrayInfo); + } else if (IsEnabled) { + // There is a special case, where some commands get called when we are running in the new editor. For + // example, if the user would be focused on a node in Solution Explorer and press Ctrl + I. Our walk + // across the controls wouldn't ever land us on the new editor itself, which is a command target. In + // those instances, we want to try and get that target and see if we can actually run the command in + // the new editor. If not, we'll revert to the old way. + if (IdeApp.Workbench?.ActiveDocument?.GetContent<ICustomCommandTarget> () is ICustomCommandTarget customCommandTarget) { + var updater = customCommandTarget.GetCommandUpdater (cmd.Id); + if (updater != null) { + updater.Run (info.SourceTarget, info); + } else { + cmd.DefaultHandler.InternalUpdate (info); + } + } else { + cmd.DefaultHandler.InternalUpdate (info); + } } - else if (IsEnabled) - cmd.DefaultHandler.InternalUpdate (info); info.Enabled &= IsEnabled; } |