Click here to Skip to main content
15,885,278 members
Articles / Programming Languages / C#

Calculating Metrics and Searching with a CodeDOM (Part 8)

Rate me:
Please Sign up or sign in to vote.
5.00/5 (7 votes)
6 Mar 2013CDDL7 min read 22K   682   10  
Calculating metrics on and searching a CodeDOM.
// 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
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)


Written By
Software Developer (Senior)
United States United States
I've been writing software since the late 70's, currently focusing mainly on C#.NET. I also like to travel around the world, and I own a Chocolate Factory (sadly, none of my employees are oompa loompas).

Comments and Discussions