Enhanced Datatip Design Notes

If you attended the recent Tech Ed in San Diego, you would have had a chance to see some of the new whiz-bang debugger features that Whidbey will ship with.  One feature that is very near to me (because I wrote it) is the new, much improved and useful datatips -- something we refer to around here as “Enhanced Datatips”. If you're not sure what I'm talking about these are the little tooltip windows that popup over top of your program's variables when you hover your mouse over them while debugging.

 

For Whidbey these little doo-dads have been replaced by a much more convenient and functional form:

In the interest of time, I didn't bother trying to get a datatip comparison between old and new using the same underlying code.  If you haven't seen these work, they work very much like the old datatips -- hover the mouse over what you want to see and it appears.  I'd like to provide some details as to how I went about designing this new widget.  This information was taken almost verbatim directly from an internal Wiki here at Microsoft, so the flow may seem a bit odd and I decided not to un-CamelCase many of the terms.

Original Datatips

Datatips are a feature of the Visual Studio Debugger and have been in existence since Visual C++ 1.0.  They were originally designed to provide quick and immediate feedback of the state of variables within a program, without requiring any more user interaction than moving and hovering the mouse.  This feature came to become a staple of the product that most developers cannot live without.

The design and implementation of Datatips have not changed in any dramatic way since their introduction.  Though they can be immensely useful, they do have their share of issues.  Among the most problematic issues:

  • They disappear after 30 seconds.
  • Many variables are more than simple data types; they are more typically compound data types containing member fields.  The current datatip model does not support the ability to see member fields except through simple stringizing of the datatype via the language expression evaluator or an auto-expansion rule.
  • They cannot differentiate between simple property evaluation and function evaluation.  Because datatips are so easy to be made to appear, they have been artificially limited to not doing any sort of func-eval, which currently includes property evaluation.

Enhanced Datatips

In general, the design of the EnhancedDatatips came about from a desire to keep the spirit of the old DataTip model, while providing substantial improvements in functionality.  They should not to be considered a floating watch window, but rather an alternate way of viewing data in the debugger. It's user-interface purposely deviates from that of existing debugger watch windows providing a new and complimentary data-inspection model that our users have never experienced.

HoverExpansion:

The Debugger should provide information as quickly and easily as possible, without requiring much UserInteraction. This is why the original DataTip concept was so powerful. All the user had to do is hover the MouseCursor over a variable to see what it's value was.

  • The new DataTips not only appear when the mouse is hovered over text that can be evaluated as an expression, but they also expand if the "expansion widget" is hovered over. This simulates the same experience the user used to get the tip to display in the first place.
  • This model also addresses a concern many have had over the years about the expansion boxes in the WatchWindows being too small. By removing the need for the user to click on the widget, there is one less user operation to have to go wrong.
  • How does the user know that hover expansion will work? There's not a perfect solution for that, so clicking will also expand an item.

Size and Format:

DataTips should display what is desired and only cover as much ScreenRealEstate as necessary.

  • The new datatips use a cascading model rather than a tree model. This generally allows individual values to be seen without wasting space.

Imagine you were viewing an instance of the following structure:

                 struct mystruct
                {
                        char string[80];
                        int x;
                        int y;
                }

Using a tree-based datatip, in order to see individual characters inside mystruct.string, you'd have a window open that might look like this:

         |                                                     |
        |+ s = {x=10 y=20 string=0x0012faf0 "hello world!" }  |
        | |                                                   |
        | + + string = 0x0012faf0 "hello world!"              |
        | | |                                                 |
        | | + [0] = 'h'                                       |
        | | + [1] = 'e'                                       |
        | | + [1] = 'l'                                       |
        | | + [1] = 'l'                                       |
        | | + [1] = 'o'                                       |
        | | +   :                                             |
        | | +   :                                             |
        | | - [80] = ''                                       |
        | + - x = 10                                          |
        | + - y = 20                                          |
        |                                                     |

Clearly there is a ton of wasted ScreenRealEstate.

  • If instead we use the cascading tip model, each level of the datatip would only occupy as much ScreenRealEstate as is necessary to enclose the longest value by the number of items in the tip. Plus, since the array datatip can occupy some of the space already occupied by the datatip representing s, even more ScreenRealEstate is preserved.
  • This example also demonstrates another problem. Note that the string is only a few characters long, but is contained in a character array of 80 characters. Unfortunately the debugger can't really know that you're only interested in the first 13 characters of this array, so when you expand it, you'll see all 80 elements. By putting the array elements in it's own window, a clearer mechanism for scrolling through all the members can be fashioned.
  • If the tips are still getting in the way they can be temporarily toggled to transparent by clicking the MouseWheel, or pressing the ControlKey. Releasing either returns the tips to opaque.

Integration With Existing Debugger UI

The EnhancedDatatips are not meant as a replacement for the existing watch windows. However, it is clear through usability studies that users can navigate a hierarchy tree much more quickly than they can the existing watch window tree.  However, tying the datatips to the rest of the UI provides an even richer experience for the user. 

This integration includes the ability to Add a Watch from anywhere within a cascaded tip. This way a user can quickly add an item they they would like to watch over the course of several steps.   In addition, values can be edited in-place -- right in the datatip.  These updated values are reflected throughout the rest of the debugger UI.