// The Nova Project by Ken Beckett.
// 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.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using Nova.CodeDOM;
namespace Nova.UI
{
/// <summary>
/// The view model for a <see cref="CodeDOM.CodeObject"/>.
/// </summary>
public abstract class CodeObjectVM
{
#region /* STATICS */
protected static Dictionary<Type, Func<CodeObject, bool, Dictionary<CodeObject, CodeObjectVM>, CodeObjectVM>> CreateViewModel =
new Dictionary<Type, Func<CodeObject, bool, Dictionary<CodeObject, CodeObjectVM>, CodeObjectVM>>();
static CodeObjectVM()
{
// Override any default static field values with any specified in the config file
Configuration.LoadSettings();
InitializeViewModelMappings();
}
internal static void InitializeViewModelMappings()
{
// Force calls to all static AddViewModelMapping methods on all types derived from CodeObjectVM, so that
// all Model->ViewModel mappings will be created before CreateVM() is called above.
foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
{
if (type.IsSubclassOf(typeof(CodeObjectVM)))
{
MethodInfo method = type.GetMethod("AddViewModelMapping", BindingFlags.NonPublic | BindingFlags.Static);
if (method != null)
method.Invoke(null, null);
}
}
}
/// <summary>
/// Create a child view model of the appropriate type for the specified <see cref="CodeDOM.CodeObject"/>.
/// </summary>
public static CodeObjectVM CreateVM(CodeObject codeObject, CodeObjectVM parentVM, bool isDescription, Dictionary<CodeObject, CodeObjectVM> dictionary)
{
if (codeObject != null)
{
Func<CodeObject, bool, Dictionary<CodeObject, CodeObjectVM>, CodeObjectVM> createViewModel;
if (CreateViewModel.TryGetValue(codeObject.GetType(), out createViewModel))
{
CodeObjectVM codeObjectVM = createViewModel(codeObject, isDescription, dictionary);
codeObjectVM.ParentVM = parentVM;
return codeObjectVM;
}
Log.WriteLine("ERROR: VM mapping missing for type: " + codeObject.GetType());
}
return null;
}
/// <summary>
/// Create a child view model of the appropriate type for the specified <see cref="CodeDOM.CodeObject"/>.
/// </summary>
public static CodeObjectVM CreateVM(CodeObject codeObject, CodeObjectVM parentVM, bool isDescription)
{
return CreateVM(codeObject, parentVM, isDescription, null);
}
/// <summary>
/// Create a child view model of the appropriate type for the specified <see cref="CodeDOM.CodeObject"/>.
/// </summary>
public static CodeObjectVM CreateVM(CodeObject codeObject, CodeObjectVM parentVM)
{
return CreateVM(codeObject, parentVM, false, null);
}
/// <summary>
/// Create a list of view models for the specified list of <see cref="CodeDOM.CodeObject"/>s.
/// </summary>
public static ChildListVM<T> CreateListVM<F, T>(IEnumerable<F> codeObjects, CodeObjectVM parent, Dictionary<CodeObject, CodeObjectVM> dictionary)
where F : CodeObject where T : CodeObjectVM
{
ChildListVM<T> codeObjectVMs = null;
if (codeObjects != null)
{
codeObjectVMs = new ChildListVM<T>(parent);
foreach (CodeObject codeObject in codeObjects)
codeObjectVMs.Add((T)CreateVM(codeObject, parent, false, dictionary));
}
return codeObjectVMs;
}
/// <summary>
/// Create a list of view models for the specified list of <see cref="CodeDOM.CodeObject"/>s.
/// </summary>
public static ChildListVM<T> CreateListVM<F, T>(IEnumerable<F> codeObjects, CodeObjectVM parent)
where F : CodeObject where T : CodeObjectVM
{
return CreateListVM<F, T>(codeObjects, parent, null);
}
#endregion
#region /* FIELDS */
/// <summary>
/// The underlying <see cref="CodeDOM.CodeObject"/> model.
/// </summary>
public CodeObject CodeObject;
/// <summary>
/// The parent <see cref="CodeObjectVM"/>.
/// </summary>
protected CodeObjectVM _parentVM;
/// <summary>
/// Any associated <see cref="AnnotationVM"/>s (null if none).
/// </summary>
public ChildListVM<AnnotationVM> AnnotationVMs;
/// <summary>
/// The total height of the corresponding GUI elements (whether realized or not).
/// </summary>
public double Height;
/// <summary>
/// The total width of the corresponding GUI elements (whether realized or not).
/// </summary>
public double Width;
/// <summary>
/// The Y offset of the CodeObjectVM within the parent Canvas (if applicable).
/// </summary>
public double Y;
/// <summary>
/// The X offset of the CodeObjectVM within the parent Canvas (if applicable).
/// </summary>
public double X; // Refactor display logic to eliminate the need for this?
/// <summary>
/// The top-level generated WPF UI object, or null if not currently rendered.
/// </summary>
public FrameworkElement FrameworkElement;
#endregion
#region /* CONSTRUCTORS */
/// <summary>
/// Create a view model instance for the specified <see cref="CodeDOM.CodeObject"/>.
/// </summary>
protected CodeObjectVM(CodeObject codeObject, Dictionary<CodeObject, CodeObjectVM> dictionary)
{
CodeObject = codeObject;
AnnotationVMs = CreateListVM<Annotation, AnnotationVM>(codeObject.Annotations, dictionary);
if (dictionary != null)
{
try
{
dictionary.Add(codeObject, this);
}
catch (ArgumentException)
{
throw new Exception("The same CodeObject can't appear more than once in a tree being rendered, as this doesn't allow "
+ "1-to-1 mapping with VM objects (not to mention, it will cause problems with editing of the tree). Probably a "
+ "SymbolicRef needs to have Clone() called on it.");
}
}
}
#endregion
#region /* PROPERTIES */
/// <summary>
/// The parent <see cref="CodeObjectVM"/>.
/// </summary>
public CodeObjectVM ParentVM
{
get
{
// Create the parent VM if it hasn't been done yet (can occur in tooltips)
if (_parentVM == null && CodeObject.Parent != null)
_parentVM = CreateVM(CodeObject.Parent, null, true);
return _parentVM;
}
set { _parentVM = value; }
}
#endregion
#region /* METHODS */
/// <summary>
/// Create a child view model of the appropriate type for the specified <see cref="CodeObject"/>.
/// </summary>
public CodeObjectVM CreateVM(CodeObject codeObject, bool isDescription, Dictionary<CodeObject, CodeObjectVM> dictionary)
{
return CreateVM(codeObject, this, isDescription, dictionary);
}
/// <summary>
/// Create a child view model of the appropriate type for the specified <see cref="CodeObject"/>.
/// </summary>
public CodeObjectVM CreateVM(CodeObject codeObject, bool isDescription)
{
return CreateVM(codeObject, this, isDescription, null);
}
/// <summary>
/// Create a child view model of the appropriate type for the specified <see cref="CodeObject"/>.
/// </summary>
public CodeObjectVM CreateVM(CodeObject codeObject)
{
return CreateVM(codeObject, this, false, null);
}
/// <summary>
/// Create a list of view models for the specified list of <see cref="CodeObject"/>s.
/// </summary>
public ChildListVM<T> CreateListVM<F, T>(IEnumerable<F> codeObjects, Dictionary<CodeObject, CodeObjectVM> dictionary)
where F : CodeObject where T : CodeObjectVM
{
return CreateListVM<F, T>(codeObjects, this, dictionary);
}
/// <summary>
/// Create a list of view models for the specified list of <see cref="CodeObject"/>s.
/// </summary>
public ChildListVM<T> CreateListVM<F, T>(IEnumerable<F> codeObjects)
where F : CodeObject where T : CodeObjectVM
{
return CreateListVM<F, T>(codeObjects, this, null);
}
/// <summary>
/// Update all <see cref="AnnotationVM"/>s to match the underlying <see cref="Annotation"/> collection.
/// </summary>
public void UpdateAnnotations()
{
AnnotationVMs = CreateListVM<Annotation, AnnotationVM>(CodeObject.Annotations);
}
/// <summary>
/// Get the absolute Y position of the object.
/// </summary>
public double GetAbsoluteY()
{
// Get the offset within the parent Canvas plus the parent Canvas absolute Y
double absoluteY = Y;
CodeObjectVM currentVM = this;
CodeObjectVM parentVM = ParentVM;
while (true)
{
// Look for the parent IBlockVM, but make sure we came from its BodyVM as opposed
// to other children such as prefixed annotations.
if (parentVM is IBlockVM)
{
BlockVM blockVM = ((IBlockVM)parentVM).BodyVM;
if (blockVM != null && blockVM.Contains(currentVM) && blockVM.Y > 0)
{
absoluteY += blockVM.Y;
break;
}
}
if (absoluteY == 0)
absoluteY = parentVM.Y;
currentVM = parentVM;
parentVM = currentVM.ParentVM;
}
return absoluteY;
}
#endregion
#region /* ANNOTATIONS */
/// <summary>
/// Annotations (comments, attributes, directives, messages) associated with the current code object.
/// </summary>
public ChildListVM<AnnotationVM> Annotations
{
get { return AnnotationVMs; }
}
/// <summary>
/// True if the code object has any annotations.
/// </summary>
public bool HasAnnotations
{
get { return (AnnotationVMs != null && AnnotationVMs.Count > 0); }
}
/// <summary>
/// Returns the <see cref="DocSummaryVM"/>, or null if none exists.
/// </summary>
public virtual DocSummaryVM GetDocSummary()
{
return (AnnotationVMs != null ? Enumerable.FirstOrDefault(Enumerable.Select<DocCommentVM, DocSummaryVM>(
Enumerable.OfType<DocCommentVM>(AnnotationVMs), delegate(DocCommentVM annotationVM) { return annotationVM.GetDocSummary(); })) : null);
}
#endregion
#region /* FORMATTING */
/// <summary>
/// Determines if the view model object appears as the first item on a line.
/// </summary>
public bool IsFirstOnLine
{
get { return CodeObject.IsFirstOnLine; }
}
#endregion
#region /* RENDERING */
/// <summary>
/// Rendering behavior flags (passed through rendering methods).
/// </summary>
[Flags]
public enum RenderFlags : uint
{
/// <summary>No flags set.</summary>
None = 0x00000000,
/// <summary>Suppress indentation of the current block.</summary>
NoBlockIndent = 0x00000001,
/// <summary>Suppress parens if empty (used by NewOperators).</summary>
NoParensIfEmpty = 0x00000002,
/// <summary>Suppress rendering of EOL comments (used by RenderList).</summary>
NoEOLComments = 0x00000004,
/// <summary>Suppress the next newline because it's already been pre-rendered.</summary>
SuppressNewLine = 0x00000008,
/// <summary>Suppress type arguments when rendering a Type (used by TypeRef rendering).</summary>
SuppressTypeArgs = 0x00000010,
/// <summary>Object needs a space prefix if it's not the first thing on the line.</summary>
PrefixSpace = 0x00000040,
/// <summary>Object is a child prefix of another - the IsFirstOnLine flag actually means IsLastOnLine.</summary>
IsPrefix = 0x00000080,
/// <summary>Suppress the space suffix on a prefix object.</summary>
NoSpaceSuffix = 0x00000100,
/// <summary>Object is on the right side of a Dot operator.</summary>
HasDotPrefix = 0x00000200,
/// <summary>Render as a declaration (might differ from references).</summary>
Declaration = 0x00001000,
/// <summary>Rendering an attribute (hide "Attribute" suffix, hide parens if empty).</summary>
Attribute = 0x00002000,
/// <summary>Increase the indentation level for any future newlines.</summary>
IncreaseIndent = 0x00004000,
/// <summary>Render a terminator (after a statement or a ChildList).</summary>
HasTerminator = 0x00008000,
/// <summary>Suppress rendering of separators (commas) between items in a ChildList.</summary>
NoItemSeparators = 0x00010000,
/// <summary>Suppress rendering of post annoations (used by ChildList).</summary>
NoPostAnnotations = 0x00020000,
/// <summary>Suppress translations (used by DocText text rendering only).</summary>
NoTranslations = 0x00040000,
/// <summary>Do NOT increase the indentation level for any future newlines.</summary>
NoIncreaseIndent = 0x00100000,
/// <summary>Force the use of a border (GUI rendering only).</summary>
ForceBorder = 0x00200000,
/// <summary>Hide the border of the current object (GUI rendering only).</summary>
NoBorder = 0x00400000,
/// <summary>Cause a 1-space indent within the containing border (GUI rendering only).</summary>
SpaceIndent = 0x00800000,
// The following flags are passed through all child rendering calls without being automatically cleared:
/// <summary>Suppress brackets when rendering a TypeRef for an array type (used for NewArray with jagged arrays).</summary>
SuppressBrackets = 0x01000000,
/// <summary>Suppress Line-Col info in tooltips.</summary>
SuppressLineCol = 0x01000000,
/// <summary>Render comments in-line (using block style instead of EOL style).</summary>
CommentsInline = 0x02000000,
/// <summary>Render as description (no body, show full signature on references, etc.).</summary>
Description = 0x04000000,
/// <summary>Show any parent types of the type being rendered.</summary>
ShowParentTypes = 0x08000000,
/// <summary>Object being rendered is inside a documentation comment.</summary>
InDocComment = 0x10000000,
/// <summary>Suppress rendering of any prefix annotations on the current object (used to suppress them for the first item in a ChildList).</summary>
NoPreAnnotations = 0x20000000,
/// <summary>Suppress rendering of first/last newlines in doc comment content (used by DocComment classes).</summary>
NoTagNewLines = 0x40000000,
/// <summary>Format numerics in hex.</summary>
FormatAsHex = 0x80000000,
/// <summary>Mask of flags that propagate through all rendering calls.</summary>
PassMask = SuppressBrackets | CommentsInline | Description | ShowParentTypes | InDocComment | NoPreAnnotations | NoTagNewLines | FormatAsHex,
/// <summary>Flags used during length determination for alignment purposes.</summary>
LengthFlags = NoPreAnnotations | NoEOLComments | NoPostAnnotations
}
public static readonly Brush PalerGreen = new SolidColorBrush(Color.FromRgb(215, 255, 215));
public static readonly Brush DarkPalerGreen = new SolidColorBrush(Color.FromRgb(159, 255, 159));
public static readonly Brush DarkPink = new SolidColorBrush(Color.FromRgb(255, 155, 172));
public static readonly Brush DarkLavender = new SolidColorBrush(Color.FromRgb(189, 189, 242));
public static readonly Brush NORMAL_BRUSH = Brushes.Black;
public static readonly Brush IDENTIFIER_BRUSH = NORMAL_BRUSH;
public static readonly Brush KEYWORD_BRUSH = Brushes.Blue;
public static readonly Brush TYPE_BRUSH = new SolidColorBrush(Color.FromRgb(43, 145, 175));
public static readonly Brush OPERATOR_BRUSH = Brushes.Purple;
public static readonly Brush STRING_BRUSH = Brushes.Maroon;
public static readonly Brush STRING_ESC_BRUSH = Brushes.Magenta;
public static readonly Brush NUMERIC_BRUSH = Brushes.Olive;
public static readonly Brush NUMERIC_ALPHA_BRUSH = Brushes.DarkOrange;
public static readonly Brush COMMENT_BRUSH = Brushes.Green;
public static readonly Brush COMMENT_TAG_BRUSH = Brushes.Gray;
public static readonly Brush COMMENT_SPECIAL_BRUSH = Brushes.DarkBlue;
public static readonly Brush PUNC_BRUSH = Brushes.Gray;
public static readonly Brush DIRECTIVE_BRUSH = Brushes.Magenta;
public static readonly Brush ERROR_BRUSH = Brushes.Red;
public static readonly Brush WARNING_BRUSH = Brushes.Goldenrod;
public static readonly Brush REDUNDANT_BRUSH = Brushes.Gray;
public virtual Brush BorderBrush
{
get { return Brushes.LightGray; }
}
public virtual Brush BackgroundBrush
{
get { return Brushes.White; }
}
public virtual int BorderHPad
{
get { return 1; }
}
public virtual int BorderVPad
{
get { return 1; }
}
/// <summary>
/// Render a description of the code object.
/// This is generally the shortest representation that uniquely identifies objects, even if
/// they have the same name, for example: type or return type, name, type parameters, parameters.
/// </summary>
public void RenderDescription(CodeRenderer renderer)
{
// Render the code object, suppressing any leading newline
Render(renderer, RenderFlags.Description | RenderFlags.ShowParentTypes | RenderFlags.SuppressNewLine | RenderFlags.IncreaseIndent | RenderFlags.ForceBorder);
}
/// <summary>
/// Render the code object into WPF objects in the specified StackPanel, rendering the area defined by startY/endY.
/// </summary>
public CodeRenderer Render(StackPanel stackPanel, double startY, double endY)
{
CodeRenderer renderer = new CodeRenderer(stackPanel, startY, endY, CodeObject.IsGenerated);
try
{
// Measure all objects first before rendering them
renderer.Measuring = true;
Render(renderer, RenderFlags.SuppressNewLine);
renderer.Measuring = false;
Render(renderer, RenderFlags.SuppressNewLine);
}
catch (Exception ex)
{
string message = Log.Exception(ex, "rendering");
renderer.RenderText(message, ERROR_BRUSH, this);
}
return renderer;
}
/// <summary>
/// Un-render (release UI objects).
/// </summary>
public virtual void UnRender()
{
FrameworkElement = null;
ChildListHelpers.UnRender(AnnotationVMs);
}
protected internal virtual bool HasBorder()
{
return true;
}
public virtual void Render(CodeRenderer renderer, RenderFlags flags)
{
// This base routine should really always be overridden with custom rendering logic, but
// we'll support default rendering using ToString().
renderer.RenderText(base.ToString(), IDENTIFIER_BRUSH, this);
}
protected virtual void RenderBefore(CodeRenderer renderer, RenderFlags flags)
{
if (!flags.HasFlag(RenderFlags.NoPreAnnotations))
RenderAnnotations(renderer, flags);
}
protected virtual void RenderAfter(CodeRenderer renderer, RenderFlags flags)
{
if (!flags.HasFlag(RenderFlags.NoPostAnnotations))
RenderAnnotations(renderer, AnnotationFlags.IsPostfix, flags);
}
protected void CreateBorder(CodeRenderer renderer, RenderFlags flags, Brush borderBrush, Brush backgroundBrush)
{
renderer.CreateBorder(borderBrush, backgroundBrush, this, flags.HasFlag(RenderFlags.SpaceIndent) ? CodeRenderer.SpaceWidth : 0, BorderVPad, BorderHPad);
}
protected void CreateBorder(CodeRenderer renderer, RenderFlags flags)
{
renderer.CreateBorder(BorderBrush, BackgroundBrush, this, flags.HasFlag(RenderFlags.SpaceIndent) ? CodeRenderer.SpaceWidth : 0, BorderVPad, BorderHPad);
}
public virtual void RenderVisible(CodeRenderer renderer, RenderFlags flags)
{
renderer.RenderVisibleList(AnnotationVMs, flags);
}
/// <summary>
/// Get the <see cref="FrameworkElement"/> to be highlighted when the object is selected.
/// </summary>
public virtual FrameworkElement GetSelectionElement()
{
return FrameworkElement;
}
public virtual void RenderToolTip(CodeRenderer renderer, RenderFlags flags)
{
TypeRefBaseVM.RenderType(renderer, CodeObject.GetType(), flags, this);
renderer.RenderText(" : ", NORMAL_BRUSH, TextStyle.Proportional | TextStyle.Bold);
RenderDescription(renderer);
RenderSummaryCommentInToolTip(renderer);
RenderMessagesInToolTip(renderer, flags);
}
public void RenderToolTip(CodeRenderer renderer)
{
RenderToolTip(renderer, RenderFlags.None);
}
public void RenderSummaryCommentInToolTip(CodeRenderer renderer)
{
DocSummaryVM docSummary = GetDocSummary();
if (docSummary != null)
{
// Always render a newline, and suppress any on the object - this handles two different situations: where
// the doc summary has 0 or more than 1 newlines.
renderer.NewLine();
// Rendering doc comments in Description mode suppresses XML tags, and NoTagNewLines suppresses
// any leading and/or trailing newline on the DocSummary content.
docSummary.Render(renderer, RenderFlags.Description | RenderFlags.NoTagNewLines | RenderFlags.SuppressNewLine);
}
}
public void RenderMessagesInToolTip(CodeRenderer renderer, RenderFlags flags)
{
if (!flags.HasFlag(RenderFlags.SuppressLineCol))
RenderLineColInToolTip(renderer);
if (AnnotationVMs != null)
{
foreach (AnnotationVM annotation in AnnotationVMs)
{
if (annotation is MessageVM)
annotation.Render(renderer, RenderFlags.None);
}
}
}
public void RenderLineColInToolTip(CodeRenderer renderer)
{
int lineNumber = CodeObject.LineNumber;
if (lineNumber != 0)
renderer.RenderNameValue("Line-Col", CodeObject.LineNumber + "-" + CodeObject.ColumnNumber);
}
#region /* ANNOTATION RENDERING */
/// <summary>
/// Render all regular (non-EOL, non-Infix, non-Postfix, non-Message) annotations (comments, attributes, compiler directives).
/// </summary>
public void RenderAnnotations(CodeRenderer renderer, RenderFlags flags)
{
if (AnnotationVMs != null && !flags.HasFlag(RenderFlags.Description))
{
flags |= RenderFlags.IsPrefix;
foreach (AnnotationVM annotationVM in AnnotationVMs)
{
Annotation annotation = annotationVM.Annotation;
if (!annotation.IsEOL && !annotation.IsInfix && !annotation.IsPostfix && !(annotationVM is MessageVM))
annotationVM.Render(renderer, flags | (annotationVM.IsFirstOnLine ? 0 : RenderFlags.CommentsInline));
}
}
}
/// <summary>
/// Render all EOL comments.
/// </summary>
public void RenderEOLComments(CodeRenderer renderer, RenderFlags flags)
{
if (AnnotationVMs != null && !flags.HasFlag(RenderFlags.NoEOLComments) && !flags.HasFlag(RenderFlags.Description))
{
foreach (AnnotationVM annotationVM in AnnotationVMs)
{
Annotation annotation = annotationVM.Annotation;
if (annotationVM is CommentVM && annotation.IsEOL && !annotation.IsInfix)
renderer.RenderEOLComment((CommentVM)annotationVM);
}
}
}
/// <summary>
/// Render all Infix EOL comments.
/// </summary>
public void RenderInfixEOLComments(CodeRenderer renderer, RenderFlags flags)
{
if (AnnotationVMs != null && !flags.HasFlag(RenderFlags.NoEOLComments) && !flags.HasFlag(RenderFlags.Description))
{
foreach (AnnotationVM annotationVM in AnnotationVMs)
{
Annotation annotation = annotationVM.Annotation;
if (annotationVM is CommentVM && annotation.IsEOL && annotation.IsInfix)
renderer.RenderEOLComment((CommentVM)annotationVM);
}
}
}
/// <summary>
/// Render all Infix comments with the specified mask.
/// </summary>
public void RenderInfixComments(CodeRenderer renderer, AnnotationFlags infixMask, RenderFlags flags)
{
if (AnnotationVMs != null && !flags.HasFlag(RenderFlags.NoEOLComments) && !flags.HasFlag(RenderFlags.Description))
{
foreach (AnnotationVM annotationVM in AnnotationVMs)
{
if (annotationVM is CommentVM)
{
Annotation annotation = annotationVM.Annotation;
if (infixMask != 0 ? (annotation.AnnotationFlags & AnnotationFlags.InfixMask) == infixMask : annotation.IsInfix)
{
if (flags.HasFlag(RenderFlags.PrefixSpace) && !annotation.IsEOL)
renderer.RenderText(" ", NORMAL_BRUSH, annotationVM);
renderer.RenderEOLComment((CommentVM)annotationVM);
}
}
}
}
}
/// <summary>
/// Render all specified Infix or Postfix annotations (comments, compiler directives).
/// </summary>
public void RenderAnnotations(CodeRenderer renderer, AnnotationFlags positionFlag, RenderFlags flags)
{
if (AnnotationVMs != null && !flags.HasFlag(RenderFlags.Description))
{
foreach (AnnotationVM annotationVM in AnnotationVMs)
{
Annotation annotation = annotationVM.Annotation;
if (annotation.AnnotationFlags.HasFlag(positionFlag))
{
if (annotationVM is CommentVM)
renderer.RenderEOLComment((CommentVM)annotationVM);
else
annotationVM.Render(renderer, RenderFlags.None);
}
}
}
}
public Brush GetMessageBrush(Brush defaultBrush, RenderFlags flags)
{
MessageSeverity worstMessageType = CodeObject.GetWorstMessageType();
Brush brush;
switch (worstMessageType)
{
case MessageSeverity.Error:
brush = ERROR_BRUSH; break;
case MessageSeverity.Warning:
brush = WARNING_BRUSH; break;
default:
brush = defaultBrush; break;
}
return brush;
}
#endregion
#endregion /* RENDERING */
#region /* COMMANDS */
public static readonly RoutedCommand AutomaticCodeOptimizationsCommand = new RoutedCommand("Automatic Code Optimizations", typeof(CodeObjectVM));
public static void BindCommands(Window window)
{
WPFUtil.AddCommandBinding(window, AutomaticCodeOptimizationsCommand, automaticCodeOptimizations_Executed);
}
private static void automaticCodeOptimizations_Executed(object sender, ExecutedRoutedEventArgs e)
{
CodeObject.AutomaticCodeCleanup = !CodeObject.AutomaticCodeCleanup;
CodeRenderer.ReRenderAll();
}
#endregion
}
}