void UninitializeActiveTab(TabStateDecompile tabState, bool forceIsInActiveTabGroup) { var tabManager = tabState == null ? null : tabState.Owner as TabManager<TabStateDecompile>; bool isInActiveTabGroup = tabGroupsManager.ActiveTabGroup == tabManager || forceIsInActiveTabGroup; var oldView = tabState == null ? null : tabState.TextView; if (oldView != null && isInActiveTabGroup) { Debug.Assert(debug_CommandBindings_Count + oldView.CommandBindings.Count == this.CommandBindings.Count); foreach (CommandBinding binding in oldView.CommandBindings) this.CommandBindings.Remove(binding); Debug.Assert(debug_CommandBindings_Count == this.CommandBindings.Count); UninstallTextEditorListeners(oldView); } }
public SetFocusWhenVisible(TabStateDecompile tabState) { this.tabState = tabState; tabState.TextView.TextEditor.TextArea.IsVisibleChanged += textArea_IsVisibleChanged; }
void tabManager_OnAddRemoveTabState(TabManager<TabStateDecompile> tabManager, TabManagerAddType addType, TabStateDecompile tabState) { var view = tabState.TextView; if (addType == TabManagerAddType.Add) { tabState.PropertyChanged += tabState_PropertyChanged; RemoveCommands(view); view.TextEditor.TextArea.MouseRightButtonDown += delegate { view.GoToMousePosition(); }; view.TextEditor.WordWrap = sessionSettings.WordWrap; view.TextEditor.Options.HighlightCurrentLine = sessionSettings.HighlightCurrentLine; view.TextEditor.Options.EnableRectangularSelection = false; if (OnDecompilerTextViewAdded != null) OnDecompilerTextViewAdded(this, new DecompilerTextViewEventArgs(view)); } else if (addType == TabManagerAddType.Remove) { tabState.PropertyChanged -= tabState_PropertyChanged; if (OnDecompilerTextViewRemoved != null) OnDecompilerTextViewRemoved(this, new DecompilerTextViewEventArgs(view)); } else if (addType == TabManagerAddType.Attach) { if (OnDecompilerTextViewAttached != null) OnDecompilerTextViewAttached(this, new DecompilerTextViewEventArgs(view)); } else if (addType == TabManagerAddType.Detach) { if (OnDecompilerTextViewDetached != null) OnDecompilerTextViewDetached(this, new DecompilerTextViewEventArgs(view)); } else throw new InvalidOperationException(); }
void SelectTreeViewNodes(TabStateDecompile tabState, ILSpyTreeNode[] nodes) { if (!IsActiveTab(tabState)) return; // This isn't perfect, but let's assume the TE has focus if the treeview doesn't. // We should normally check for: // Keyboard.FocusedElement == tabState.TextView.TextEditor.TextArea // but a menu could be open in the text editor, and then the above expression fails. bool hasKeyboardFocus = !(Keyboard.FocusedElement is SharpTreeViewItem); var old = tabState.ignoreDecompilationRequests; try { tabState.ignoreDecompilationRequests = true; treeView.SelectedItems.Clear(); if (nodes.Length > 0) { treeView.FocusNode(nodes[0]); // This can happen when pressing Ctrl+Shift+Tab when the treeview has keyboard focus if (treeView.SelectedItems.Count != 0) treeView.SelectedItems.Clear(); treeView.SelectedItem = nodes[0]; // FocusNode() should already call ScrollIntoView() but for some reason, // the ScrollIntoView() does nothing so add another call. // Background priority won't work, we need ContextIdle prio this.Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action(delegate { var item = treeView.SelectedItem as SharpTreeNode; if (item != null) treeView.ScrollIntoView(item); })); } foreach (var node in nodes) treeView.SelectedItems.Add(node); } finally { tabState.ignoreDecompilationRequests = old; } // The treeview stole the focus; get it back if (hasKeyboardFocus) DelaySetFocus(tabState); }
static bool MustRefresh(TabStateDecompile tabState, LoadedAssembly asm) { var asms = new HashSet<LoadedAssembly>(); asms.Add(asm); return DecompileCache.IsInModifiedAssembly(asms, tabState.DecompiledNodes) || DecompileCache.IsInModifiedAssembly(asms, tabState.TextView.References); }
internal bool SetActiveTab(TabStateDecompile tabState) { if (tabGroupsManager.SetActiveTab(tabState)) { SetTextEditorFocus(tabState.TextView); return true; } return false; }
bool BackCommand(TabStateDecompile tabState) { if (tabState == null) return false; if (tabState.History.CanNavigateBack) { NavigateHistory(tabState, false); return true; } return false; }
internal TabStateDecompile CloneTab(TabStateDecompile tabState, bool decompile = true) { if (tabState == null) return null; return CreateTabState(CreateSavedTabState(tabState), tabState.DecompiledNodes, decompile); }
void RecordHistory(TabStateDecompile tabState) { if (tabState == null) return; var dtState = tabState.TextView.GetState(tabState.DecompiledNodes); if (dtState != null) tabState.History.UpdateCurrent(new NavigationState(dtState, tabState.Language)); tabState.History.Record(new NavigationState(tabState.DecompiledNodes, tabState.Language)); }
internal void Save(TabStateDecompile tabState) { if (tabState == null) return; var textView = tabState.TextView; if (tabState.DecompiledNodes.Length == 1) { if (tabState.DecompiledNodes[0].Save(textView)) return; } textView.SaveToDisk(tabState.Language, tabState.DecompiledNodes, new DecompilationOptions() { FullDecompilation = true }); }
bool? DecompileNodes(TabStateDecompile tabState, DecompilerTextViewState state, bool recordHistory, Language language, ILSpyTreeNode[] nodes, bool forceDecompile = false) { if (tabState.ignoreDecompilationRequests) return null; // Ignore all nodes that have been deleted nodes = FilterOutDeletedNodes(nodes); if (tabState.HasDecompiled && !forceDecompile && tabState.Equals(nodes, language)) { if (state != null) tabState.TextView.EditorPositionState = state.EditorPositionState; return false; } if (tabState.HasDecompiled && recordHistory) RecordHistory(tabState); tabState.HasDecompiled = true; tabState.SetDecompileProps(language, nodes); if (nodes.Length == 1 && nodes[0].View(tabState.TextView)) { tabState.TextView.CancelDecompileAsync(); return true; } tabState.TextView.DecompileAsync(language, nodes, new DecompilationOptions() { TextViewState = state, DecompilerTextView = tabState.TextView }); return true; }
// Returns true if we could decompile the reference bool JumpToReferenceAsyncInternal(TabStateDecompile tabState, bool canLoad, object reference, Func<bool, bool, bool> onDecompileFinished) { ILSpyTreeNode treeNode = FindTreeNode(reference); if (treeNode != null) { var helper = new OnShowOutputHelper(tabState.TextView, onDecompileFinished, treeNode); var nodes = new[] { treeNode }; bool? decompiled = DecompileNodes(tabState, null, false, tabState.Language, nodes); if (decompiled == false) { helper.Abort(); onDecompileFinished(true, false); } SelectTreeViewNodes(tabState, nodes); return true; } else if (reference is dnlib.DotNet.Emit.OpCode) { string link = "http://msdn.microsoft.com/library/system.reflection.emit.opcodes." + ((dnlib.DotNet.Emit.OpCode)reference).Code.ToString().ToLowerInvariant() + ".aspx"; try { Process.Start(link); } catch { } return true; } else if (canLoad && reference is IMemberDef) { // Here if the module was removed. It's possible that the user has re-added it. var member = (IMemberDef)reference; var module = member.Module; if (module == null) // Check if it has been deleted return false; var mainModule = module; if (module.Assembly != null) mainModule = module.Assembly.ManifestModule; if (!string.IsNullOrEmpty(mainModule.Location) && !string.IsNullOrEmpty(module.Location)) { // Check if the module was removed and then added again foreach (var m in assemblyList.GetAllModules()) { if (mainModule.Location.Equals(m.Location, StringComparison.OrdinalIgnoreCase)) { foreach (var asmMod in GetAssemblyModules(m)) { if (!module.Location.Equals(asmMod.Location, StringComparison.OrdinalIgnoreCase)) continue; // Found the module var modDef = asmMod as ModuleDefMD; if (modDef != null) { member = modDef.ResolveToken(member.MDToken) as IMemberDef; if (member != null) // should never fail return JumpToReferenceAsyncInternal(tabState, false, member, onDecompileFinished); } break; } return false; } } } // The module has been removed. Add it again var loadedAsm = new LoadedAssembly(assemblyList, mainModule); loadedAsm.IsAutoLoaded = true; assemblyList.AddAssembly(loadedAsm, true, false, false); return JumpToReferenceAsyncInternal(tabState, false, reference, onDecompileFinished); } else return false; }
public SetFocusWhenVisible(TabStateDecompile tabState, UIElement uiElem) { this.tabState = tabState; this.uiElem = uiElem; uiElem.IsVisibleChanged += uiElem_IsVisibleChanged; }
void SetTabFocus(TabStateDecompile tabState) { if (tabState == null) return; if (!IsActiveTab(tabState)) return; if (tabState.TabItem.Content == null) return; UIElement uiElem; if (tabState.IsTextViewInVisualTree) { var textView = tabState.TextView; if (textView.waitAdornerButton.IsVisible) { SetFocusIfNoMenuIsOpened(textView.waitAdornerButton); return; } uiElem = textView.TextEditor.TextArea; } else uiElem = tabState.TabItem.Content as UIElement; Debug.Assert(uiElem != null); if (uiElem == null) return; if (!uiElem.IsVisible) new SetFocusWhenVisible(tabState, uiElem); else SetFocusIfNoMenuIsOpened(uiElem); }
void NavigateHistory(TabStateDecompile tabState, bool forward) { var dtState = tabState.TextView.GetState(tabState.DecompiledNodes); if(dtState != null) tabState.History.UpdateCurrent(new NavigationState(dtState, tabState.Language)); var newState = forward ? tabState.History.GoForward() : tabState.History.GoBack(); var nodes = newState.TreeNodes.Cast<ILSpyTreeNode>().ToArray(); SelectTreeViewNodes(tabState, nodes); DecompileNodes(tabState, newState.ViewState, false, newState.Language, nodes); SetLanguage(newState.Language); }
void SetScaleValue(TabStateDecompile tabState, double scale) { if (scale == 1) { tabState.TextView.TextEditor.TextArea.LayoutTransform = Transform.Identity; tabState.TextView.TextEditor.TextArea.ClearValue(TextOptions.TextFormattingModeProperty); } else { var st = tabState.TextView.TextEditor.TextArea.LayoutTransform as ScaleTransform; if (st == null) tabState.TextView.TextEditor.TextArea.LayoutTransform = st = new ScaleTransform(); if (scale < MIN_ZOOM) scale = MIN_ZOOM; else if (scale > MAX_ZOOM) scale = MAX_ZOOM; // We must set it to Ideal or the text will be blurry TextOptions.SetTextFormattingMode(tabState.TextView.TextEditor.TextArea, TextFormattingMode.Ideal); st.ScaleX = scale; st.ScaleY = scale; } }
static SavedTabState CreateSavedTabState(TabStateDecompile tabState) { var savedState = new SavedTabState(); savedState.Language = tabState.Language.Name; savedState.Paths = new List<FullNodePathName>(); savedState.ActiveAutoLoadedAssemblies = new List<string>(); foreach (var node in tabState.DecompiledNodes) { savedState.Paths.Add(node.CreateFullNodePathName()); var autoAsm = GetAutoLoadedAssemblyNode(node); if (!string.IsNullOrEmpty(autoAsm)) savedState.ActiveAutoLoadedAssemblies.Add(autoAsm); } savedState.EditorPositionState = tabState.TextView.EditorPositionState; return savedState; }
internal TabStateDecompile CloneTabMakeActive(TabStateDecompile tabState, bool decompile = true) { var clonedTabState = CloneTab(tabState, decompile); if (clonedTabState != null) tabGroupsManager.ActiveTabGroup.SetSelectedTab(clonedTabState); return clonedTabState; }
TabStateDecompile CreateNewTabState(TabManager<TabStateDecompile> tabManager, Language language = null) { var tabState = new TabStateDecompile(language ?? sessionSettings.FilterSettings.Language); return tabManager.AddNewTabState(tabState); }
void ForceDecompile(TabStateDecompile tabState) { DecompileNodes(tabState, null, false, tabState.Language, tabState.DecompiledNodes, true); }
TabStateDecompile CreateTabState(TabStateDecompile tabState, SavedTabState savedState, IList<ILSpyTreeNode> newNodes = null, bool decompile = true) { var nodes = new List<ILSpyTreeNode>(savedState.Paths.Count); if (newNodes != null) nodes.AddRange(newNodes); else { foreach (var asm in savedState.ActiveAutoLoadedAssemblies) this.assemblyList.OpenAssembly(asm, true); foreach (var path in savedState.Paths) { var node = assemblyListTreeNode.FindNodeByPath(path); if (node == null) { nodes = null; break; } nodes.Add(node); } } if (decompile) { if (nodes != null) { var tmpNodes = nodes.ToArray(); var helper = new OnShowOutputHelper(tabState.TextView, (success, hasMovedCaret) => decompilerTextView_OnShowOutput(success, hasMovedCaret, tabState.TextView, savedState), tmpNodes); DecompileNodes(tabState, null, false, tabState.Language, tmpNodes); } else AboutPage.Display(tabState.TextView); } return tabState; }
internal void CloseTab(TabStateDecompile tabState) { var tabManager = (TabManager<TabStateDecompile>)tabState.Owner; tabManager.CloseTab(tabState); }
void DelaySetFocus(TabStateDecompile tabState) { if (tabState != null) { // The TreeView steals the focus so we can't just set the focus to the text view // right here, we have to wait a little bit. // This is ugly, but we must use Normal prio to get rid of flickering (tab getting // inactive followed by getting active). However, this doesn't work all the time // (test: right-click tab, open new tab), so we must start another one at a lower // priority in case the treeview steals the focus....... this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(delegate { if (ActiveTabState == tabState) SetTextEditorFocus(tabState.TextView); })); this.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(delegate { if (ActiveTabState == tabState) SetTextEditorFocus(tabState.TextView); })); } }
bool IsActiveTab(TabStateDecompile tabState) { return tabGroupsManager.ActiveTabGroup.ActiveTabState == tabState; }
void ZoomDecrease(TabStateDecompile tabState) { if (tabState == null) return; var scale = GetScaleValue(tabState); scale -= scale / 10; SetScaleValue(tabState, scale); }
void InitializeActiveTab(TabStateDecompile tabState, bool forceIsInActiveTabGroup) { var tabManager = tabState == null ? null : tabState.Owner as TabManager<TabStateDecompile>; bool isInActiveTabGroup = tabGroupsManager.ActiveTabGroup == tabManager || forceIsInActiveTabGroup; var newView = tabState == null ? null : tabState.TextView; if (newView != null) { if (isInActiveTabGroup) { Debug.Assert(debug_CommandBindings_Count == this.CommandBindings.Count); this.CommandBindings.AddRange(newView.CommandBindings); SetLanguage(tabState.Language); } } bool dontSelect; if (tabManager != null && tabManager_dontSelectHack.TryGetValue(tabManager, out dontSelect) && dontSelect) { } else if (tabState == null) { if ((tabGroupsManager.AllTabGroups.Count == 1 && tabGroupsManager.ActiveTabGroup.ActiveTabState == null)) { var old = TreeView_SelectionChanged_ignore; try { TreeView_SelectionChanged_ignore = true; treeView.SelectedItems.Clear(); } finally { TreeView_SelectionChanged_ignore = old; } } else if (isInActiveTabGroup) treeView.SelectedItems.Clear(); } else SelectTreeViewNodes(tabState, tabState.DecompiledNodes); if (isInActiveTabGroup) ClosePopups(); if (newView != null && isInActiveTabGroup) InstallTextEditorListeners(newView); }
void ZoomReset(TabStateDecompile tabState) { if (tabState == null) return; SetScaleValue(tabState, 1); }
internal void tabManager_OnSelectionChanged(TabManager<TabStateDecompile> tabManager, TabStateDecompile oldState, TabStateDecompile newState) { var oldView = oldState == null ? null : oldState.TextView; var newView = newState == null ? null : newState.TextView; UninitializeActiveTab(oldState, false); InitializeActiveTab(newState, false); if (IsActiveTab(newState)) SetTextEditorFocus(newView); if (OnDecompilerTextViewChanged != null) OnDecompilerTextViewChanged(this, new DecompilerTextViewChangedEventArgs(oldView, newView)); }
double GetScaleValue(TabStateDecompile tabState) { var st = tabState.TextView.TextEditor.TextArea.LayoutTransform as ScaleTransform; if (st != null) return st.ScaleX; return 1; }
void ActivateWindow(TabInfo info) { LastActivatedTabState = info.TabState; MainWindow.Instance.SetActiveTab(info.TabState); }