Mark Miller
  • Working with Color in CodeRush

    Working with color in source code has never been as easy or intuitive as it should be. Looking at hex values or a color name like Bisque and then trying to imagine what that color looks like is a challenge. Finding the correct color to use in a new style in a CSS file is also challenging.

    Furthermore, going from color to code is rarely a picnic.

    Fortunately, CodeRush 10.1 brings developers much closer to the real colors with new Color features. In this post I’ll discuss CodeRush features for working with color, both new and old.

    Generating Color Declarations from HTML

    This Intelligent Paste feature has been around for years. Simply copy an HTML color declaration (e.g., “#4B70BC”) and paste that inside a C# or VB file inside a method, property accessor, or inside a type (but not in a member) on an empty line, and you’ll get something like this (C# example shown):

    ShowColorSmartPaste

    This intelligent paste will create a local variable or a field, depending upon where you paste. As with all Intelligent Paste operations, you can press Undo to get the literal contents of the clipboard if you don’t like the CodeRush version. All Intelligent Paste operations are defined on the Intelligent Paste options page. Follow these steps to get there if you want to see them all:

    1. From the DevExpress menu, select "Options...".
    2. In the tree view on the left, navigate to this folder: Editor\Clipboard
    3. Select the "Intelligent Paste" options page.

    Note: This page level is Advanced, and will only be visible if the Level combo on the lower-left of the Options dialog is set to Advanced or Expert.

    Working with Color Declarations from Templates

    When working with color from templates, the mnemonic to remember is “CL”.

    Normally (without CodeRush), if I want to bring up a list of named colors using Intellisense, I have to type in “Color.”. With CodeRush installed, I can now simply type “CL” (lower case is fine) followed by the space bar to expand the template, and this is important: the caret must be at a location where a Color expression is valid (so not on an empty line but instead as a parameter to a method or an assignment to a variable or a property. Also, the active project must have a reference to System.Drawing or System.Windows.Media (CodeRush will add the appropriate namespace reference to the source file if needed).

    If you need a color from the SystemColors class, expand the “SYC” template (again, lowercase is fine, but for clarity I like to specify templates using uppercase letters).

    Back to that CL mnemonic. You can combine this shortcut with other CodeRush code templates that work with types. For example, MCL will generate a method that returns a Color, VCL will create a variable declaration (local, parameter, or field) of type Color, and ACL will generate an auto-implemented property of type Color. There are also PCL (for properties of type Color with backing store) and NCL for newly-initialized variables of type Color.  And there is “CL.E” for Color.Empty.

    Try these in a project that references System.Drawing or System.Windows.Media.

    Color Swatches in the Code

    Remember that color declaration we generated at the top of this post when I pasted a color reference into the code? You probably noticed that bluish rectangle under the word Color. Here’s that screen shot again:

    ShowColorSmartPaste

    And here’s a variation with different values:

    ColorSwatch

    Those rectangles appearing below the Color type reference are color swatches. These are very cool. Now you no longer have to reverse engineer RGB color values in your head to figure out exactly what color you’re looking at in the code.

    NamedColorSwatches

    The CodeRush Color Dialog

    So what happens when you want to edit a color in the code? Good news: just click the color swatch with the mouse and up pops the CodeRush Color dialog, which looks like this:

    ColorPickerAppears

    The CodeRush Color dialog consists of several pages, which we’ll examine in a moment. At the bottom of the CodeRush Color dialog is a sample color swatch which reveals the selected color, and to the right of the sample is a Favorites button. FavoritesButton

    We’ll talk more about the cool things you can do with favorite colors in a moment. But first, let’s take a look at the pages.

    The Color Picker

    The “Picker” page, the one you see in the screen shot above, is perhaps the most weighty. If you need to pick a color based on hue, saturation, brightness, red, green, or blue, you can do it here. You can also set opacity, enter an HTML color (including shorthand for web-safe colors such as “369”), and change a selected color to it’s nearest web-safe neighbor. And you can select a color from an existing image or window appearing on your desktop by clicking the eye-dropper tool. EyeDropper

    When working with color, you can use one of two mechanisms: red, green, & blue or hue, saturation & brightness (RGB and HSB). You may prefer to work with HSB on the Picker page since these attributes make it easy to change the brightness or the saturation without modifying the hue, which can produce nice color variations like this:

    Variations

    or this:

    Variations2

    Keeping most of the UI colors in the same hue is useful for reducing visual noise in a user interface.

    Regardless of which of the two mechanisms you choose to work in, specifying a color on this page is always a convergence of three values. I like to visualize this as a cube which holds all colors. If I’m working in RGB, the dimensions of that cube are 256x256x256.

    Here’s an example of a three-dimensional arrangement of colors organized by saturation (width), brightness (height), and hue (depth):

    ColorCube

    So to specify a color in this three-dimensional space the Picker page gives you a two-dimensional grid, like this:

    TwoDimensionalGrid

    and a one-dimensional vertical gradient, like this:

    OneDimensionalGrid

    These two controls work together to let you specify any color in this three-dimensional space. The vertical gradient allows you to select any plane in this space, and two-dimensional grid lets you select a color on that plane.

    The vertical gradient is useful when you want to isolate one of the three attributes of the cube you’re working with onto a single dimension, allowing adjustments to only one value while keeping the other two attributes static.

    To isolate an attribute just click its corresponding radio button on this page.

    For example, to isolate the Saturation attribute, click the “Sat:” radio button.

     BySaturation

    Notice the labels on the two-dimensional grid have changed to show Brightness on the vertical axis and Hue on the horizontal axis.

    Isolating the Brightness attribute looks like this:

    ByBrightness

    Things get interesting when you isolate one of the RGB channels. For example, here’s Red:

    ByRed

    Here you can see where the color will go as you increase or decrease the RGB values.

    Here’s what it looks like when you isolate the Green channel:

    ByGreen

    And for completeness, here’s what it looks like when you isolate the Blue channel:

    ByBlue

    If you need a color from the desktop, click the Eyedropper button EyeDropper and then click on the color you want. A sample of the color under the eyedropper will appear below the button, and to the right you’ll see a magnified portion of the screen with a rectangle in the center representing the eyedropper position.

    PickColor

    If we’re working with a color that isn’t web safe, the “Make Web Safe” button will be enabled. Clicking it will to take the selected color to its nearest web-safe neighbor, like this:

     WebSafeNow

    Right above the Make Web Safe button is the hex edit control, useful for copying or pasting hex triplet representations of color (for example, “B6005A”). You can also use a three-digit shorthand when representing web safe colors, for example enter “369” in the hex edit control and you’ll get this:

    WebSafeShorthand

    Which is shorthand for #336699.

    Web Colors

    Speaking of web-safe colors, let’s switch to the Web page, where you can select from all 216 web-safe colors:

    WebSafeColors

    Named Colors

    Here’s the Named page for .NET colors based on the X11 color names:

    NamedColors

    System Colors

    SystemColors

    Document Colors

    The Document page shows all the colors defined in the active document (before taking this screen shot I opened a C# class which defined many colors):

    DocumentColors

    Favorite Colors

    And finally, we have the Favorites page, which might initially look like this:

    Favorites

    The favorites page holds favorite colors in groups called palettes.

    There are three interesting buttons on the top row of this page:

    DeleteSelectedColor Delete Selected Color
    DeleteActivePalette Delete Active Palette
    CreateNewPalette Create New Palette

    You can rename the active palette simply by typing in a new name in the combo box at the top of the dialog (press Enter to commit the change or Escape to cancel). For example, let’s rename this palette to “My Faves”, like this:

    MyFaves

    Press Enter to commit the change, or you can commit the rename by simply moving focus away to another control.

    At the bottom of the CodeRush Color dialog, to the right of the color sample, sits the Favorites button. FavoritesButton

    If you click the button, the sample color will be added to the active palette page.

    AddFavorite

    Let’s add another color to this page. Click on the Named color tab, select DarkOrange:

    DarkOrange

    Then click the Favorite button, and watch what happens under the mouse:

    ReturnButtonBig

    The Favorites button changes to a Return button, so a single click on this can get you right back to the page you started from. This makes it easy to add several favorite colors from anywhere in the CodeRush Color window.

    There’s one more cool thing you can do with favorite colors. To demonstrate, let’s create a new palette page. Click the Create New Palette button. CreateNewPalette

    Now let’s go to the Picker page and find a favorite color, like this:

    DevExpressBlue

    For this demo I’m grabbing the DevExpress blue from the web site using the Eyedropper.

    Now, right-click the Favorite button and select Add Color Distribution, then click the number of colors of varying lightness you want to add in the same hue as this color. I’ll select 21.

    AddColorDistribution

    Which generates 21 colors based on the selected color, like this:

    DevExpressColorDistribution

    Generating the Color Reference

    Once you have the color you want, just click the OK button and the active color reference will be replaced with a reference to the color selected. Here’s the DevExpress blue placed in a C# file after clicking OK:

    DevExpressColorInCode

    Oh, and if you’re still wondering what Bisque looks like, here it is:

      ColorBisque

    We hope you enjoy the CodeRush features that make working with color easier. As always, let us know what we can do to improve your development experience.

  • CodeRush Xpress & CodeRush Ready for Visual Studio 2010

    Both CodeRush Xpress and CodeRush have been released this week. CodeRush Xpress went final and became available only a few seconds after Visual Studio 2010 became officially released.

    The full version of CodeRush 10.1 is available on the Betas tab of your client center download page.

    While CodeRush Xpress is final, the full version of CodeRush 10.1 is expected to be final by the end of April when the rest of DXperience 10.1 ships.

  • Spend a Day with Miller in Vegas! (Free CodeRush Training)

    Hey kids,

    Ever wish you could spend the day with your good old buddy Mark Miller in a Las Vegas training room?

     MillerHangingOut

    Just sitting back, shooting the breeze and talking about whatever CodeRush thing is on your mind? Well the good folks at DevExpress are working hard to make your dream come true. :-)

    That’s right, kids. DevExpress is putting together a full day’s worth of formal CodeRush training, tentatively scheduled for Thursday the 15th of April, the day after the DevConnections conference and the official launch of Visual Studio 2010 in Las Vegas. And like the title of this blog post reads, this training session will be 100% free.

    Not only will it be free, but DevExpress will also be giving away prizes, we’ll hear from a special guest speaker from the Visual Studio team at Microsoft, and there’ll be some yummy food to eat. All courtesy of DevExpress. It’s crazy I tell you. Absolutely crazy. :-)

    As for content, we’ll start off the morning talking about CodeRush Xpress, then we’ll move into the more powerful features of the full version of CodeRush, wrapping up with extensibility, showing how to radically customize your IDE. The course content will look something like this:

    • CodeRush Xpress
      • Navigation
      • Selection
      • Clipboard Features
      • Declaration from Usage
      • Refactoring
      • Performance/Memory Comparison
    • CodeRush
      • Selection Embedding
      • Other Productivity Features
        • Intellassist
        • Auto Declare
        • Smart Semi-Colon
        • Smart Parens
      • Templates
      • Code Issues
      • Test Runner
      • More Code Providers
      • More Clipboard Features
      • More Refactorings
      • Other Language Features
        • ASP.NET
        • XAML
        • JavaScript
        • etc.
      • Extensibility
        • Third Party Plug-ins
        • Introduction – Creating a Simple Plug-in
        • Creating Refactorings
        • Creating Code Providers
        • Creating Code Issues

    So what’s the catch, you ask? It’s simple. We need to get a sense of how many people will show up, and we need to know very soon so we can book a room big enough to hold everyone. If this event sounds like your kind of fun and you can make it to Vegas in April, post a comment below to let us know of your intentions to be there. I expect that soon we’ll create a registration page so you can lock in your spot, and when that’s page is available we’ll let you know through blogs, tweeting, shouting and otherwise general mayhem.

  • Slicing and Dicing Strings with CodeRush for Visual Studio

    CodeRush brings powerful string manipulation features to Visual Studio. Here are a few of my favorites:

    Splitting Strings

    When you need to break a string literal into two or three pieces. For example, let’s start with the following text:

     

    public string GetGreetingText(int daysLeft)
    {
      return "Welcome back, customer. \nSo glad to see you. Days remaining on our special offer: " + daysLeft.ToString();
    }

    I can place the caret (the flashing I-beam that marks the editor’s insertion point) right before “Days remaining” text and press the CodeRush/Refactor! key (Ctrl+` by default) and then choose Split String.

    SplitStringInto2

    This will split the string into two pieces.

    Next, let’s select the last two expressions on this line:

    SelectLastExpression

    Press the CodeRush/Refactor! key, and choose Extract Method to create a new method called GetDaysRemaining, like this:

    GetDaysRemaining

    Use String.Format

    Next, move the caret down inside the string inside the GetDaysRemaining method. Press the CodeRush/Refactor! key and select Use String.Format.

    UseStringFormat

    This neatly combines the concatenation into a single string that is easy to read and so much easier to translate (translating string fragments is much harder to do when grammatical rearrangements are needed as part of the localization).

    Speaking of translation…

    Extract String to Resource

    Move the caret inside the “Days remaining…” string. Press the CodeRush/Refactor! key and select Extract String to Resource, then select “Create new resource file”.

    ExtractStringToResource

    CodeRush will create a new resource file to hold this string, and highlight the resource identifier for an easy rename (tip: I like to use Camel Case Nav and Camel Case Select – Alt plus Left or Right arrow keys with Shift to select -- to quickly trim a long identifier down to a reasonable size). Let’s call this resource “DaysRemaining”.

    DaysRemainingResource

    Placing strings in resource files is a good first step to preparing your code for translation.

    Splitting Strings, Revisited

    The CodeRush Split String refactoring has a bonus feature built in: the ability to split a string into three pieces. Just select the portion of the string that you want to pull out and apply the refactoring. For example, in the code above, there is a “\n” appearing inside the string. This “\n” may be confusing to translators, it makes the string harder to read, and it may not be the most appropriate way to terminate lines on some platforms, so let’s take it out and replace it with the Environment.NewLine expression.

    First, select the “\n”:

    SelectSlashN

    Press the CodeRush/Refactor! key and select Split String

    ApplySplitStringIntoThree

    Applying the refactoring will leave you with this:

    SplitStringInto2Applied

    Notice the “\n” string fragment is selected for easy editing. Now we can use CodeRush’s “enl” template to replace the “\n” with a proper Environment.NewLine expression.

    AfterEnvironmentNewLine

    Introduce Format Item

    See that “Welcome back, customer.” string in the code above? It would be great if we could actually pass in the customer’s name in place of the text “customer”. That would make the greeting certainly more personal. It’s easy to do this with CodeRush. Just select the part of the string that you want to replace, and press the CodeRush/Refactor! key, like this:

    IntroduceFormatItemPreviewHint

    Apply the Introduce Format Item refactoring to get this:

    AppliedIntroduceFormatItem

    Notice that once again the extracted string is selected for easy editing. Now let’s promote this string to a parameter. Press the CodeRush/Refactor! key and select Promote to Parameter.

    PromoteToParameter

    And give the new parameter a meaningful name, like customerName:

    PromoteToParameterAfterRename

    Converting Text to Strings

    Sometimes you need to work with a text coming from another environment, and that text span several lines or contain quote characters (that would need to be escaped). So in this example I used the “ms” template to create a method that returns a string, and I expanded the “r” template to get the return keyword and then I pasted in some XAML code that creates a TextBlock:

    private string GetTextBlock()
    {
      return <TextBlock
      Canvas.Left="25" Canvas.Top="5"
     
    Foreground="Teal" FontFamily="Verdana" FontSize="18" FontWeight="Bold"
     
    Text="Sample Output" />;
    }

    Of course this code will not compile. Fortunately we have CodeRush installed so getting it into its desired shape is easy. Just select the text we want to convert, press the CodeRush/Refactor! key and select Embed Selection | To string, like this:

    EmbedString

    CodeRush will convert the text into a string, like this:

    ConvertToString

    Nice. Notice how the quotes are properly escaped and the separate lines are now concatenated together.

    Now, suppose you wanted to parameterize some of the values in this string. For example, turn the “Sample Output” into a “text” parameter. How would you do that? Well, you should already know how. Just select the text, split the string, and promote it to a parameter.

    Wrapping Up

    If you’re not already using CodeRush, you should be. This post has covered only a portion of the tools and features that work with strings, and working with strings is only a very small tip of the very large iceberg of power that is CodeRush. CodeRush is the fastest, most powerful, and most memory-efficient developer productivity add-on available for Visual Studio.

  • The Extensible Test Runner You’ve Been Waiting For

    We’ve been hard at work fine-tuning the CodeRush Test Runner, and we’re getting excited.

    This screen shot contains a few clues as to why we’re so pumped up:

     FirstShot

    We’re pleased with the UI. Notice in the screen shot above how failing tests are easy to spot while the less-important information is rendered in a lower contrast that’s easy on the eyes. Also, we’ve done some work on the tree list to reduce the number of clicks needed to get to tests of interest. And there’s a handy filter text box at the top.

    So it looks pretty. But more importantly, the Test Runner supports all the popular testing frameworks right out of the box, including VSTest, NUnit (including different flavors mixed in with various extensions), and the oft-neglected xUnit and MbUnit. The screen shot above is taken from a solution that includes test cases for all of these frameworks.

    CodeRush customers will also receive full source code to the plug-ins we ship that provide all this luscious unit testing support. So if you want to extend support for any of these unit test frameworks, it’s easy. Or if you want to add support for a brand new unit testing framework, you all have the sample code you need to get started. That is cool.

    Test results also appear in the code:

     TestStatus

    You can run test cases from the Test Runner, or from the code itself by clicking one of the Test Runner icons that appear next to the unit test attributes (as shown in the screen shot above).

    The Test Runner debuts in CodeRush 9.3 (beta is internal testing and will available soon if not already by the time you read this). I’ll be showing the Test Runner at PDC in Los Angeles this week, so if you’re in LA stop by our booth and check it out.

  • Here's a Picture Worth 1000 Words...

    Derek Reynolds says it all with a single screen shot.

  • DX Labs: Single Code Base Driving GDI and WPF Simultaneously from CodeRush Plug-ins

    Since the beginning, CodeRush has been extensible.

    The cardinal rule for extensible architectures:

    New revs of the framework can’t break existing plug-ins.

    Through each release the IDE Tools team responsible for CodeRush has strived to ensure backward and forward compatibility for 3rd-party plug-ins. And throughout the years, we have by and large achieved this goal.

    And along comes the Visual Studio 2010 editor.

    Based entirely on WPF.

    Which kind of mucks things up for anyone writing plug-ins that paint on the editor. Those plug-ins rely upon DXCore events that pass a GDI Graphics instance which makes it easy to paint on the editor surface. But VS 2010 has effectively removed GDI from the equation.

    Which leaves us with a few obvious options:

    • Split the code base (attempt to maintain two code bases)
    • Abandon GDI and support for GDI-based dev environments (e.g., VS 2008 and earlier)

    The cost of splitting the code base is potentially very high, not only for us but also for customers. For us, it makes the code more complex to maintain, and it potentially creates a scenario where CodeRush customers remaining in VS 2008 or VS 2005 might go without issue fixes and enhancements occurring in the latest version of CodeRush working in WPF land. Moving to an entirely new code base has similar consequences for customers remaining in GDI land.

    There is also a less obvious solution which is to provide a GDI layer on top of the WPF layer in VS 2010, which would allow editor-surface painting plug-ins written in VS 2008 to continue to work in VS 2010. I’m about as comfortable with this approach/hack as I am squeezing my pet elephant Jorge into my brand new bright yellow Borat-style bathing suit. While such a configuration may appear stylish from a distance and to some degree addresses the forward compatibility challenge, it brings the risk of some serious chafing. It just doesn’t fit in a WPF world where you want to be able to take advantage of everything that Microsoft has added to VS 2010 that works with WPF.

    And so we’ve walked away from this more obscure option too.

    So we continued to consider the problem.

    Around this time I was working on a blog post on Implementing Code Providers, and this bit of code that shows up in the post was on my mind:

    private void cpImplementUnimplementedProperty_PreparePreview(object sender, PrepareContentPreviewEventArgs ea)
    {
      Property oldProperty = GetProperty(ea.Element);
      if (oldProperty == null)
        return;

      ElementBuilder elementBuilder = ea.NewElementBuilder();
      string newCode = GetNewPropertyDeclaration(elementBuilder, oldProperty);

      ea.AddCodePreview(oldProperty.Range.Start, newCode.Trim());
      ea.AddStrikethrough(oldProperty.Range);
    }

    Notice the last two lines of code. These two lines of code add a visual strikethrough markup over the old code in the editor, and they also add a Code Preview window that’s attached to the code. Both of these look like this:

    Notice the complete lack of anything even remotely resembling GDI whatsoever in those two lines of code. The GDI-heavy code to actually paint the strikethrough and the event handling necessary to support this are abstracted away from the plug-in already. This was all a result of work we did years ago to make it super easy to create preview hints for refactorings and code providers. (That’s why CodeRush includes over 185 refactorings – the architecture makes it super-easy to make them.)

    Considering the strikethrough code example above eventually led us to this question:

    • Can we abstract all aspects of painting out to a layer that plug-ins can exploit to paint on the editor, without requiring explicit knowledge of GDI or WPF?

    If you’re familiar with both GDI and WPF, you understand the magnitude of this question. At first glance it seems incredibly challenging. GDI painting is event-driven, and WPF painting is more of a one-time assembly of pieces, and changes to the pieces can result in automatic updates to the images. GDI has none of this. These drawing frameworks are so radically different in so many ways it seems impossible. Of course, on the IDE Tools team, we don’t use the word impossible. We might use “economically infeasible” and “No F*in’ Way”, but never impossible. So the question really became one of economic feasibility. Could we abstract enough of what we needed from these two drawing frameworks in time for the VS 2010 release?

    The answer appears to be YES. To be clear, there are two steps here:

    1. Abstract the painting layer, and create two different engines that map the abstraction to either WPF or GDI.
    2. Update any existing source code that does anything remotely GDI so it uses the new painting layer.

    Drawbacks:

    1. We have to port GDI-specific code in existing plug-ins to the new framework. Third party developers using GDI to paint as well will also need to be ported if they want to work in VS 2010.

    Benefits:

    1. Single source code base as we move forward.
    2. Plug-ins using the new painting layer are likely to work in all versions of Visual Studio that support .NET. If you’re a plug-in developer working with CodeRush or DXCore you don’t need to worry about which drawing framework or which version of Visual Studio you will support.

    I find this quite exciting because it removes the weight from the decision of whether to work in WPF or to stay in GDI, and that may be a decision developers out there are facing.

    Let’s take a look at a real example from the source code for the upcoming CodeRush 10 for VS 2010.

    Disclaimer: This is a DevExpress Labs preview. Everything here is subject to change until we release!

    The CodeRush stack-based markers feature paints a small triangle on the editor to indicate the position of markers dropped by the developer. Using the new framework, if we want to put something on the editor we start with a descendant of the CRVisualAdornment, like this:

    public class CRMarkerAdornment : CRVisualAdornment

      public CRMarkerAdornment(IElementFrame frame) 
      : base(frame)
      {  
      } 
     
      public override void Render(IDrawingSurface surface) 
      {  
        // TODO: Render the marker.
      } 
     
      public override Size GetSize() 
      {  
        return new Size(10, 10); 
      }  
    }

    The GetSize override allows the adornment to tell the drawing engine how big it is. The Render method override is where we place the code that will actually draw the triangle. That code might look something like this:

      public override void Render(IDrawingSurface surface) 
      {  
        Point topPoint = new Point(5, 5); 
        double halfBase = 2.5;
        double height = 5;
      
        Point[] points = { 
                             new Point(topPoint.X, topPoint.Y), 
                             new Point(topPoint.X - halfBase, topPoint.Y + height),
                             new Point(topPoint.X + halfBase, topPoint.Y + height) 
                           }; 
     
        surface.DrawPolygon(_FillColor, _OutlineColor, points); 
      }

    IDrawingSurface looks a bit like the GDI Graphics object. _FillColor and _OutlineColor are fields of type ColorProperty (more on this in a bit), and their declarations look like this:

      ColorProperty _FillColor;
      ColorProperty _OutlineColor;
     

    We initialize these fields in our constructor:

      public CRMarkerAdornment(IElementFrame frame) 
      : base(frame) 
      { 
        _FillColor = new ColorProperty(Colors.Blue); 
        _OutlineColor = new ColorProperty(Colors.DarkBlue); 
      }

    ColorProperty is cool. If we use ColorProperties in the Render override, any changes to these values are automatically reflected in the editor, regardless of the platform we are rendering in.

    So, for example, if we wanted to create a new transient marker with a short life span of 20 seconds, we could visually indicate that lifespan by changing the values of the ColorProperties over time (for example, changing the transparency of the color).

    Let’s give our CRMarkerAdornment new properties so we can do just that:

      public Color FillColor 
      { 
        get { return _FillColor.Value; } 
        set { _FillColor.Value = value; } 
      } 
      public Color OutlineColor 
      { 
        get { return _OutlineColor.Value; } 
        set { _OutlineColor.Value = value; } 
      }

    Notice these exposed properties are of type Color, not ColorProperty.

    And that’s it! Now we have a graphic element that paints in both WPF and GDI. I’m pretty sure this has never been done before. The full source looks like this:

    public class CRMarkerAdornment : CRVisualAdornment
    {
      ColorProperty _FillColor;
      ColorProperty _OutlineColor;  
      
      public CRMarkerAdornment(IElementFrame frame) 
      : base(frame) 
      { 
        _FillColor = new ColorProperty(Colors.Blue); 
        _OutlineColor = new ColorProperty(Colors.DarkBlue); 
      } 
     
      public override void Render(IDrawingSurface surface) 
      {  
        Point topPoint = new Point(5, 5); 
        double halfBase = 2.5; 
        double height = 5; 
     
        Point[] points = { 
                             new Point(topPoint.X, topPoint.Y), 
                             new Point(topPoint.X - halfBase, topPoint.Y + height),
                             new Point(topPoint.X + halfBase, topPoint.Y + height) 
                           }; 
     
        surface.DrawPolygon(_FillColor, _OutlineColor, points); 
      } 
     
      public override Size GetSize() 
      { 
        return new Size(10, 10); 
      } 
     
      public Color FillColor 
      { 
        get { return _FillColor.Value; } 
        set { _FillColor.Value = value; } 
      } 
      public Color OutlineColor 
      { 
        get { return _OutlineColor.Value; } 
        set { _OutlineColor.Value = value; } 
      }
    }

    By now you might be wondering what namespace holds the types Color, Point, Colors, and Size from the code above. In implementing this framework, we had three choices:

    1. Use System.Drawing and convert to WPF types when we need to paint with WPF.
    2. Use System.Windows and convert to GDI types when we need to paint with GDI.
    3. Use a completely new set of types and convert those to the needed types when painting.

    Choice #3 seems to clearly involve the most work. It means the GDI and WPF engines must each implement type conversion, so one might be inclined walk away from that option. However, the first two choices will penalize some customers, forcing both WPF and GDI assemblies to be loaded when only one is really necessary. So we went with choice #3.

    So now we have a CRVisualAdornment descendant that paints a triangle on the surface of the editor. There are several ways to add this adornment to the editor. One way is to do something like this:

    IElementFrame frame = ea.CreateFrame(new SourceRange(10, 20, 10, 21)); 

    CRMarkerAdornment
    markerAdornment = new CRMarkerAdornment(frame);
    markerAdornment.PenColor = Colors.Red; 
    markerAdornment.OutlineColor = Colors.DarkRed; 

    ea.AddAdornment(markerAdornment);

    The “ea” in the sample code above represents the event arguments to an unspecified event handler. Adornments can be added in response to a number of IDE events, such as opening a document or scrolling. Adornments can also be added programmatically at any time. The first line in the code above creates a new IElementFrame implementer, which essentially marks a rectangular region in the code using lines and columns. So this marker starts on line 10 at character 20, and runs to character 21 on that same line. Passing the IElementFrame implementer to our CRMarkerAdornment constructor allows the Marker to automatically stick to the code, so when you scroll the marker will scroll too.

  • Miller on DNR TV -- Intelligent Code Generation in Visual Studio with CodeRush

    I'm deep in code and surfacing briefly only to mention this DNR TV session I recorded with Carl Franklin. The session gives you a taste of how to create language-independent intelligent code generators inside Visual Studio that work with CodeRush or CodeRush Xpress. For anyone who prefers watching a movie over reading DXCore plug-in tutorial blog posts, this one's for you:

    http://www.dnrtv.com/default.aspx?showNum=152

    For developers interested in creating refactorings instead of code providers, just drop a RefactoringProvider onto your form instead of the CodeProvider -- all other steps remain the same.

    Note: The source is available as a link at the bottom of the DNR TV page. This source includes extension methods for anyone working in a version of CodeRush earlier than 9.27. If you're using 9.27 or higher, those extension methods are redundant. Check out the source even if you watch and follow the video, because it includes additional functionality not covered in the video.

  • Miller on Hanselminutes

    I sat down with Scott Hanselman this week and discussed CodeRush architecture, breaking the rules, and my allegedly massive head.

    Get it here:

    http://www.hanselminutes.com/default.aspx?showID=196

  • CodeRush Test Runner In-source UI Preview

    Lately I've had my head deep in code, and Mehul has done me the favor of blogging about our new Test Runner, in development. See Mehul's blog post for a preview of the new Test Runner in-source UI.

3 4 5 6 7
8
9 10 11 12
LIVE CHAT

Chat is one of the many ways you can contact members of the DevExpress Team.
We are available Monday-Friday between 7:30am and 4:30pm Pacific Time.

If you need additional product information, write to us at info@devexpress.com or call us at +1 (818) 844-3383

FOLLOW US

DevExpress engineers feature-complete Presentation Controls, IDE Productivity Tools, Business Application Frameworks, and Reporting Systems for Visual Studio, along with high-performance HTML JS Mobile Frameworks for developers targeting iOS, Android and Windows Phone. Whether using WPF, ASP.NET, WinForms, HTML5 or Windows 10, DevExpress tools help you build and deliver your best in the shortest time possible.

Copyright © 1998-2017 Developer Express Inc.
All trademarks or registered trademarks are property of their respective owners