// Nova.Studio - a GUI test framework for the Nova.CodeDOM C# object model library.
// Copyright (C) 2007-2012 Inevitable Software, all rights reserved.
// Released under the Common Development and Distribution License, CDDL-1.0: http://opensource.org/licenses/cddl1.php
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using Nova.Analysis;
using Nova.CodeDOM;
using Nova.UI;
namespace Nova.Studio
{
/// <summary>
/// Interaction logic for CodeWindow.xaml
/// </summary>
public partial class CodeWindow : UserControl
{
#region /* FIELDS */
protected string _description;
protected CodeObjectVM _codeVM;
protected bool _textViewEnabled;
protected double _windowHeight;
protected double _verticalScrollOffset;
protected double _fontHeight;
protected bool _skipFirstScrollEvent = true;
protected CodeRenderer _renderer;
protected Dictionary<CodeObject, CodeObjectVM> _codeObject2VM = new Dictionary<CodeObject, CodeObjectVM>();
// Save values for text view
protected readonly GridLength _textColumnWidth;
protected readonly Thickness _codeBorderMargin;
#endregion
#region /* CONSTRUCTORS */
public CodeWindow(string description, CodeObjectVM codeVM)
{
InitializeComponent();
BindCommands(Application.Current.MainWindow);
_description = description;
// Create a new CodeObjectVM tree, so that are changes are reflected and all VMs are added to the local dictionary
_codeVM = CodeObjectVM.CreateVM(codeVM.CodeObject, codeVM.ParentVM, false, _codeObject2VM);
_fontHeight = 15; // Default - changes in Render()
_textColumnWidth = mainGrid.ColumnDefinitions[1].Width;
_codeBorderMargin = codeBorder.Margin;
// WPF tooltips are an unbelievable nightmare!! Any ToolTip set to null will inherit from the parent, and
// doing ToolTipService.SetIsEnabled(control, false) has the SAME effect! Stopping tooltip inheritance requires
// both setting a non-null value, and then hacking the display so that it's off-screen!!!
// THIS IS NO LONGER USED in favor of custom tooltips, and moved the TabItem tooltip to the Header to prevent it
// from stupidly cascading to all controls on the tab.
//mainGrid.ToolTip = "";
//ToolTipService.SetVerticalOffset(mainGrid, int.MaxValue); // Force off-screen to prevent display
}
#endregion
#region /* PROPERTIES */
public string Description
{
get { return _description; }
}
public CodeObjectVM CodeVM
{
get { return _codeVM; }
}
public bool TextViewEnabled
{
get { return _textViewEnabled; }
set { _textViewEnabled = value; }
}
#endregion
#region /* METHODS */
protected static readonly GridLength ZeroGridLength = new GridLength(0);
protected static readonly Thickness ZeroThickness = new Thickness(0);
/// <summary>
/// Render the code contained within this editor object.
/// </summary>
public void Render(double windowHeight)
{
using (new WaitCursor())
{
_windowHeight = windowHeight;
if (_codeVM != null)
{
// Reset statistics
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
// Populate types combobox
if (_codeVM is CodeUnitVM)
PopulateTypesComboBox(((CodeUnitVM)_codeVM).CodeUnit);
// Measure and render the code into the panel
codePanel.Children.Clear();
_renderer = _codeVM.Render(codePanel, _verticalScrollOffset, _verticalScrollOffset + _windowHeight);
_renderer.ToolTipContextMenuOpening = codeViewer_ContextMenuOpening;
_renderer.CommandBindings = Application.Current.MainWindow.CommandBindings;
_fontHeight = CodeRenderer.CodeFontHeight;
// Add "end-of-file" marker
TextBlock textBlock = new TextBlock
{
Text = "",
Foreground = Brushes.Black,
ToolTip = "End of File",
FontFamily = CodeRenderer.CodeFontFamily,
FontSize = CodeRenderer.CodeFontSize
};
codePanel.Children.Add(textBlock);
if (!CodeRenderer.VirtualizeRendering)
{
// Log statistics
string statistics = "Render '" + _description + "', elapsed time: " + stopWatch.Elapsed.TotalSeconds.ToString("N3");
if (_renderer != null)
{
statistics += ", TextBlocks=" + _renderer.TextBlockCount + ", WrapPanels=" + _renderer.WrapPanelCount
+ ", StackPanels=" + _renderer.StackPanelCount + ", Borders=" + _renderer.BorderCount;
}
Log.WriteLine(statistics);
}
}
// Render the text view
RenderTextView();
}
}
/// <summary>
/// Render the text view of the code.
/// </summary>
public void RenderTextView()
{
if (_textViewEnabled)
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
textView.Text = (_codeVM != null ? _codeVM.CodeObject.AsText() : null);
textView.FontFamily = CodeRenderer.CodeFontFamily;
textView.FontSize = CodeRenderer.CodeFontSize;
codeBorder.Margin = _codeBorderMargin;
mainGridSplitter.Visibility = Visibility.Visible;
mainGrid.ColumnDefinitions[1].Width = _textColumnWidth;
Log.WriteLine("Text Render '" + _description + "', elapsed time: " + stopWatch.Elapsed.TotalSeconds.ToString("N3"));
}
else
{
textView.Text = null;
codeBorder.Margin = ZeroThickness;
mainGridSplitter.Visibility = Visibility.Collapsed;
mainGrid.ColumnDefinitions[1].Width = ZeroGridLength;
}
}
/// <summary>
/// Select the specified code object within the editor (scroll until it's visible if necessary, and highlight it).
/// </summary>
public void SelectCodeObject(CodeObject codeObject)
{
if (_renderer == null) return;
_renderer.CloseToolTip();
// Get the corresponding VM for the code object
CodeObjectVM codeObjectVM;
if (_codeObject2VM.TryGetValue(codeObject, out codeObjectVM))
{
// Do a layout so that the dimensions are updated
codeScrollViewer.UpdateLayout();
// Scroll the VM into view if necessary so it will be rendered
double newScrollOffset = -1;
if (codeObjectVM is CodeUnitVM)
{
if (codeScrollViewer.VerticalOffset > 0)
newScrollOffset = 0;
}
else
{
const double margin = 10;
double absoluteY = codeObjectVM.GetAbsoluteY();
if (absoluteY < codeScrollViewer.VerticalOffset + margin)
{
newScrollOffset = absoluteY - margin;
if (newScrollOffset < 0)
newScrollOffset = 0;
}
else if (absoluteY > codeScrollViewer.VerticalOffset + codeScrollViewer.ViewportHeight - margin - _fontHeight)
newScrollOffset = absoluteY - (codeScrollViewer.ViewportHeight - margin - _fontHeight);
}
if (newScrollOffset >= 0)
{
codeScrollViewer.ScrollToVerticalOffset(newScrollOffset);
_skipFirstScrollEvent = false;
// Process pending events from the scroll so that UI objects are generated before accessing them below
WPFUtil.DoEvents();
}
// Highlight the primary UI object of the VM with an animation (skip if it's a CodeUnit)
if (!(codeObjectVM is CodeUnitVM))
{
if (codeObjectVM.FrameworkElement != null)
{
FrameworkElement frameworkElement = codeObjectVM.GetSelectionElement();
// Bring into view (horizontal scrolling might be required)
frameworkElement.BringIntoView();
// Create a centered scale transform for the element
ScaleTransform scaleTransform = new ScaleTransform();
frameworkElement.RenderTransform = scaleTransform;
frameworkElement.RenderTransformOrigin = new Point(0.5, 0.5);
// Create scaling animations, starting at 2X for Y so the layout gives extra room from the edge of the view.
// Repeat 2.5 times, so it ends at 1X. Scale Y more than X, because scaling X too much can send text behind
// following text that has a higher Z order.
DoubleAnimation animationX = new DoubleAnimation(1.2, 1.0, new Duration(new TimeSpan(0, 0, 0, 0, 200)))
{ AutoReverse = true, RepeatBehavior = new RepeatBehavior(2.5), FillBehavior = FillBehavior.Stop };
DoubleAnimation animationY = new DoubleAnimation(2.0, 1.0, new Duration(new TimeSpan(0, 0, 0, 0, 200)))
{ AutoReverse = true, RepeatBehavior = new RepeatBehavior(2.5), FillBehavior = FillBehavior.Stop };
scaleTransform.BeginAnimation(ScaleTransform.ScaleXProperty, animationX);
scaleTransform.BeginAnimation(ScaleTransform.ScaleYProperty, animationY);
}
else
{
// If no UI element was found, it's probably a hidden VM, such as the VarTypeRefVM for a ParameterDeclVM with
// an inferred type (the VM is still generated because it's used to determine the color of the parent text), so
// recursively call this routine for the parent VM to display that instead.
SelectCodeObject(codeObject.Parent);
}
}
}
}
public void ResetToolTipTimer()
{
_renderer.ResetToolTipTimer();
}
public void CloseToolTip()
{
_renderer.CloseToolTip();
}
#endregion
#region /* EVENTS */
protected void codeViewer_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
bool isToolTipContextMenu = sender is Popup;
if (!isToolTipContextMenu)
_renderer.CloseToolTip();
ContextMenu contextMenu = new ContextMenu();
// Add context specific menu items here
bool addedSpecific = false;
object source = e.Source;
if (source is Run)
source = ((Run)source).Parent;
FrameworkElement frameworkElement = source as FrameworkElement;
if (frameworkElement != null)
{
CodeObject target = GetReferenceTarget(frameworkElement);
if (target != null)
{
object targetObject = (target is SymbolicRef ? ((SymbolicRef)target).Reference : target);
if (targetObject is CodeObject && !(targetObject is Namespace) && (target is SymbolicRef || isToolTipContextMenu))
WPFUtil.AddMenuItemCommand(contextMenu, GoToDeclarationCommand, frameworkElement);
if ((target is INamedCodeObject && !(target is NamespaceDecl)) || target is SymbolicRef)
{
WPFUtil.AddMenuItemCommandWithButton(contextMenu, "Find References", FindReferencesCommand, frameworkElement);
addedSpecific = true;
}
}
CodeObjectVM codeObjectVM = frameworkElement.Tag as CodeObjectVM;
if (codeObjectVM != null)
{
string name = codeObjectVM.CodeObject.GetType().Name;
WPFUtil.AddMenuItemCommandWithButton(contextMenu, "Find " + name + (name.EndsWith("s") ? "es" : "s"), FindByTypeCommand, frameworkElement);
addedSpecific = true;
}
}
// Add general menu items:
if (!isToolTipContextMenu)
{
if (addedSpecific)
WPFUtil.AddSeparator(contextMenu);
WPFUtil.AddMenuItemCommand(contextMenu, ApplicationCommands.Close, this);
WPFUtil.AddMenuItemCommand(contextMenu, ApplicationCommands.Save, this);
WPFUtil.AddMenuItemCommand(contextMenu, MainWindow.MetricsCommand, this);
WPFUtil.AddSeparator(contextMenu);
WPFUtil.AddCheckableMenuItemCommand(contextMenu, TextViewCommand, this, _textViewEnabled);
MenuItem optionsMenu = new MenuItem { Header = "Display Options" };
WPFUtil.AddCheckableMenuItemCommand(optionsMenu, CodeRenderer.ShowBordersCommand, this, CodeRenderer.ShowBorders);
WPFUtil.AddCheckableMenuItemCommand(optionsMenu, CodeRenderer.ShowBackgroundColorsCommand, this, CodeRenderer.ShowBackgroundColors);
WPFUtil.AddCheckableMenuItemCommand(optionsMenu, CodeRenderer.UseShadingCommand, this, CodeRenderer.UseShading);
WPFUtil.AddCheckableMenuItemCommand(optionsMenu, CodeRenderer.HalfHeightBlankLinesCommand, this, CodeRenderer.HalfHeightBlankLines);
WPFUtil.AddCheckableMenuItemCommand(optionsMenu, BlockVM.TinyBracesCommand, this, BlockVM.TinyBraces);
WPFUtil.AddCheckableMenuItemCommand(optionsMenu, BlockVM.HideBracesCommand, this, BlockVM.HideBraces);
WPFUtil.AddCheckableMenuItemCommand(optionsMenu, StatementVM.HideTerminatorsCommand, this, StatementVM.HideTerminators);
WPFUtil.AddCheckableMenuItemCommand(optionsMenu, StatementVM.HideStatementParensCommand, this, StatementVM.HideStatementParens);
WPFUtil.AddCheckableMenuItemCommand(optionsMenu, MethodDeclBaseVM.HideMethodParensCommand, this, MethodDeclBaseVM.HideMethodParens);
WPFUtil.AddCheckableMenuItemCommand(optionsMenu, NewObjectVM.HideEmptyParensCommand, this, NewObjectVM.HideEmptyParens);
WPFUtil.AddCheckableMenuItemCommand(optionsMenu, WhileVM.DisplayAsDoIfNullConditionCommand, this, WhileVM.DisplayAsDoIfNullCondition);
WPFUtil.AddCheckableMenuItemCommand(optionsMenu, OperatorVM.AlternativeDisplayCommand, this, OperatorVM.UseAlternativeDisplay);
WPFUtil.AddCheckableMenuItemCommand(optionsMenu, CodeRenderer.MaximizeBordersCommand, this, CodeRenderer.MaximizeBorders);
{
MenuItem commentsMenu = new MenuItem { Header = "Comments" };
WPFUtil.AddCheckableMenuItemCommand(commentsMenu, CommentBaseVM.HideDelimitersCommand, this, CommentBaseVM.HideDelimiters);
WPFUtil.AddCheckableMenuItemCommand(commentsMenu, CommentBaseVM.HideAllCommand, this, CommentBaseVM.HideAll);
WPFUtil.AddCheckableMenuItemCommand(commentsMenu, CommentVM.UseProportionalFontCommand, this, CommentVM.UseProportionalFont);
WPFUtil.AddCheckableMenuItemCommand(commentsMenu, DocCommentVM.UseProportionalFontCommand, this, DocCommentVM.UseProportionalFont);
WPFUtil.AddCheckableMenuItemCommand(commentsMenu, DocCommentVM.AlternativeFormatCommand, this, DocCommentVM.UseAlternativeFormat);
optionsMenu.Items.Add(commentsMenu);
MenuItem literalsMenu = new MenuItem { Header = "Literals" };
WPFUtil.AddCheckableMenuItemCommand(literalsMenu, LiteralVM.CommasInNumericsCommand, this, LiteralVM.CommasInNumerics);
WPFUtil.AddCheckableMenuItemCommand(literalsMenu, LiteralVM.NoEscapesCommand, this, LiteralVM.NoEscapes);
WPFUtil.AddCheckableMenuItemCommand(literalsMenu, LiteralVM.VisibleSpacesCommand, this, LiteralVM.VisibleSpaces);
WPFUtil.AddCheckableMenuItemCommand(literalsMenu, LiteralVM.HideQuotesCommand, this, LiteralVM.HideQuotes);
optionsMenu.Items.Add(literalsMenu);
}
contextMenu.Items.Add(optionsMenu);
}
contextMenu.IsOpen = contextMenu.HasItems;
((FrameworkElement)sender).ContextMenu = contextMenu;
e.Handled = true;
}
protected static CodeObject GetReferenceTarget(FrameworkElement frameworkElement)
{
// Get the object associated with the FrameworkElement, handling hidden refs
CodeObjectVM targetVM = frameworkElement.Tag as CodeObjectVM;
if (targetVM != null)
{
CodeObject codeObject = targetVM.CodeObject;
if (!(codeObject is INamedCodeObject || codeObject is SymbolicRef))
codeObject = codeObject.HiddenRef;
return codeObject;
}
return null;
}
protected void textView_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
ContextMenu contextMenu = new ContextMenu { IsOpen = true };
// Add context specific menu items here
// Add general menu items
WPFUtil.AddMenuItemCommand(contextMenu, ApplicationCommands.Copy, this);
WPFUtil.AddSeparator(contextMenu);
WPFUtil.AddCheckableMenuItemCommand(contextMenu, TextViewCommand, this, _textViewEnabled);
((FrameworkElement)sender).ContextMenu = contextMenu;
e.Handled = true;
}
protected void codeViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
_renderer.CloseToolTip();
_windowHeight = e.ViewportHeight;
_verticalScrollOffset = e.VerticalOffset;
// Skip the first scroll event, since all necessary rendering will have already been done.
// Otherwise, render any newly visible objects (and free those that are no longer visible).
if (CodeRenderer.VirtualizeRendering && !_skipFirstScrollEvent)
{
_renderer.StartY = _verticalScrollOffset;
_renderer.EndY = _verticalScrollOffset + _windowHeight;
try
{
_codeVM.RenderVisible(_renderer, CodeObjectVM.RenderFlags.None);
}
catch { }
}
_skipFirstScrollEvent = false;
e.Handled = true;
}
private void UserControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (!IsVisible)
_renderer.CloseToolTip();
}
#endregion
#region /* TYPES/MEMBERS COMBOBOXES */
protected void PopulateTypesComboBox(CodeUnit codeUnit)
{
List<TypeDeclWrapper> typeDeclWrappers = new List<TypeDeclWrapper>();
foreach (TypeDecl typeDecl in codeUnit.GetTypeDecls(true, true))
typeDeclWrappers.Add(new TypeDeclWrapper(typeDecl));
typeDeclWrappers.Sort();
typesComboBox.ItemsSource = typeDeclWrappers;
if (typeDeclWrappers.Count == 1)
typesComboBox.SelectedIndex = 0;
}
protected void PopulateMembersComboBox(TypeDeclWrapper typeDeclWrapper)
{
List<NamedCodeObjectWrapper> namedCodeObjectWrappers = new List<NamedCodeObjectWrapper>();
foreach (INamedCodeObject member in typeDeclWrapper.TypeDecl.GetMemberDecls(true))
namedCodeObjectWrappers.Add(new NamedCodeObjectWrapper(member, typeDeclWrapper.Name));
namedCodeObjectWrappers.Sort();
membersComboBox.ItemsSource = namedCodeObjectWrappers;
}
private void typesComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
TypeDeclWrapper typeDeclWrapper = typesComboBox.SelectedItem as TypeDeclWrapper;
if (typeDeclWrapper != null)
{
SelectCodeObject(typeDeclWrapper.TypeDecl);
PopulateMembersComboBox(typeDeclWrapper);
}
}
private void membersComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
NamedCodeObjectWrapper namedCodeObjectWrapper = membersComboBox.SelectedItem as NamedCodeObjectWrapper;
if (namedCodeObjectWrapper != null)
SelectCodeObject(namedCodeObjectWrapper.NamedCodeObject as CodeObject);
}
protected class TypeDeclWrapper : IComparable<TypeDeclWrapper>
{
public TypeDecl TypeDecl;
public string Name;
public TypeDeclWrapper(TypeDecl typeDecl)
{
TypeDecl = typeDecl;
Name = typeDecl.GetFullName(true);
}
public int CompareTo(TypeDeclWrapper other) { return string.Compare(Name, other.Name); }
public override string ToString() { return Name; }
}
protected class NamedCodeObjectWrapper : IComparable<NamedCodeObjectWrapper>
{
public INamedCodeObject NamedCodeObject;
public string Name;
public NamedCodeObjectWrapper(INamedCodeObject namedCodeObject, string parentTypeName)
{
NamedCodeObject = namedCodeObject;
Name = namedCodeObject.GetFullName(true).Substring(parentTypeName.Length + 1);
}
public int CompareTo(NamedCodeObjectWrapper other) { return string.Compare(Name, other.Name); }
public override string ToString() { return Name; }
}
#endregion
#region /* COMMANDS */
public static readonly RoutedCommand GoToDeclarationCommand = new RoutedCommand("Go To Declaration", typeof(CodeWindow));
public static readonly RoutedCommand FindReferencesCommand = new RoutedCommand("Find References", typeof(CodeWindow));
public static readonly RoutedCommand FindByTypeCommand = new RoutedCommand("Find By Type", typeof(CodeWindow));
public static readonly RoutedCommand TextViewCommand = new RoutedCommand("Text View", typeof(CodeWindow));
public void BindCommands(Window window)
{
WPFUtil.AddCommandBinding(window, GoToDeclarationCommand, goToDeclaration_Executed);
WPFUtil.AddCommandBinding(window, FindReferencesCommand, findReferences_Executed);
WPFUtil.AddCommandBinding(window, FindByTypeCommand, findByType_Executed);
WPFUtil.AddCommandBinding(window, TextViewCommand, textView_Executed);
}
protected static void goToDeclaration_Executed(object sender, ExecutedRoutedEventArgs e)
{
MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;
FrameworkElement frameworkElement = e.OriginalSource as FrameworkElement;
if (frameworkElement != null)
{
// Get the target object, and navigate to it (or the referenced object if it's a SymbolicRef)
CodeObject targetCodeObject = GetReferenceTarget(frameworkElement);
CodeObject codeObject = (targetCodeObject is SymbolicRef ? ((SymbolicRef)targetCodeObject).Reference as CodeObject : targetCodeObject);
mainWindow.SelectCodeObject(codeObject);
}
}
protected void findReferences_Executed(object sender, ExecutedRoutedEventArgs e)
{
MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;
CodeWindow codeWindow = mainWindow.GetCurrentCodeWindow();
FrameworkElement frameworkElement = e.OriginalSource as FrameworkElement;
if (frameworkElement != null)
{
// Get the target object, and if it's a reference, use the referenced object
CodeObject targetCodeObject = GetReferenceTarget(frameworkElement);
object target = (targetCodeObject is SymbolicRef ? ((SymbolicRef)targetCodeObject).Reference : targetCodeObject);
CodeObject scope = null;
bool includeReferences = true;
bool includeMemberReferences = false;
bool includeDerivedTypes = false;
bool includeOverrides = false;
bool includeOverloads = false;
if (e.Parameter is string)
{
FindReferencesWindow findReferencesWindow = new FindReferencesWindow(target) { Owner = mainWindow };
if (findReferencesWindow.ShowDialog() == true)
{
// Get the options and scope from the user's selection on the dialog
includeReferences = findReferencesWindow.checkBoxReferences.IsChecked ?? true;
includeMemberReferences = findReferencesWindow.checkBoxMemberReferences.IsChecked ?? false;
includeDerivedTypes = findReferencesWindow.checkBoxDerivedTypes.IsChecked ?? false;
includeOverrides = findReferencesWindow.checkBoxOverrides.IsChecked ?? false;
includeOverloads = findReferencesWindow.checkBoxOverloads.IsChecked ?? false;
if (findReferencesWindow.radioButtonEntireSolution.IsChecked == true)
scope = mainWindow.SolutionVM.Solution;
else if (findReferencesWindow.radioButtonCurrentProject.IsChecked == true)
scope = mainWindow.GetCurrentProject();
else if (findReferencesWindow.radioButtonCurrentFile.IsChecked == true)
scope = mainWindow.GetCurrentCodeUnit();
}
}
else
{
scope = mainWindow.SolutionVM.Solution;
if (scope == null)
scope = codeWindow.CodeVM.CodeObject;
}
if (scope != null)
{
// Find all references to the target object in the appropriate scope
FindReferences findReferences = new FindReferences(target, scope)
{
IncludeReferences = includeReferences,
IncludeMemberReferences = includeMemberReferences,
IncludeDerivedTypes = includeDerivedTypes,
IncludeOverrides = includeOverrides,
IncludeOverloads = includeOverloads
};
mainWindow.findParameters.Text = "Results for: " + findReferences;
mainWindow.findParameters.Tag = findReferences;
mainWindow.BindResults(findReferences.Results);
mainWindow.tabItemResults.IsSelected = true;
// Execute the FindReferences on a thread
mainWindow.Busy = true;
WPFUtil.ExecuteActionOnThread(this, FindReferencesThread, findReferences, FindReferencesCompleted);
}
}
e.Handled = true;
}
private static void FindReferencesThread(FindReferences findReferences)
{
findReferences.Find();
}
private static void FindReferencesCompleted()
{
((MainWindow)Application.Current.MainWindow).Busy = false;
}
protected void findByType_Executed(object sender, ExecutedRoutedEventArgs e)
{
MainWindow mainWindow = (MainWindow)Application.Current.MainWindow;
CodeWindow codeWindow = mainWindow.GetCurrentCodeWindow();
FrameworkElement frameworkElement = e.OriginalSource as FrameworkElement;
if (frameworkElement != null)
{
CodeObjectVM codeObjectVM = frameworkElement.Tag as CodeObjectVM;
if (codeObjectVM != null)
{
Type targetType = codeObjectVM.CodeObject.GetType();
CodeObject scope = null;
if (e.Parameter is string)
{
FindByTypeWindow findByTypeWindow = new FindByTypeWindow { Owner = mainWindow };
findByTypeWindow.textBoxType.Text = targetType.Name;
if (findByTypeWindow.ShowDialog() == true)
{
// Get the scope from the user's selection on the dialog
if (findByTypeWindow.radioButtonEntireSolution.IsChecked == true)
scope = mainWindow.SolutionVM.Solution;
else if (findByTypeWindow.radioButtonCurrentProject.IsChecked == true)
scope = mainWindow.GetCurrentProject();
else if (findByTypeWindow.radioButtonCurrentFile.IsChecked == true)
scope = mainWindow.GetCurrentCodeUnit();
}
}
else
{
scope = mainWindow.SolutionVM.Solution;
if (scope == null)
scope = codeWindow.CodeVM.CodeObject;
}
if (scope != null)
{
// Find all objects of the target type in the appropriate scope
FindByType findByType = new FindByType(targetType, scope);
mainWindow.findParameters.Text = "Results for: " + findByType;
mainWindow.BindResults(findByType.Results);
mainWindow.tabItemResults.IsSelected = true;
// Execute the FindByType on a thread
mainWindow.Busy = true;
WPFUtil.ExecuteActionOnThread(this, FindByTypeThread, findByType, FindByTypeCompleted);
}
}
}
e.Handled = true;
}
private static void FindByTypeThread(FindByType findByType)
{
findByType.Find();
}
private static void FindByTypeCompleted()
{
((MainWindow)Application.Current.MainWindow).Busy = false;
}
protected static void textView_Executed(object sender, ExecutedRoutedEventArgs e)
{
CodeWindow codeWindow = (CodeWindow)e.Source;
codeWindow._textViewEnabled = !codeWindow._textViewEnabled;
codeWindow.RenderTextView();
e.Handled = true;
}
#endregion
}
}