CodeGuru
Earthweb Search
Forums Wireless Jars Gamelan Developer.com
CodeGuru Navigation
Member Sign In
User ID:
Password:
Remember Me:
Forgot Password?
Not a member?
Click here for more information and to register.

Become a Marketplace Partner

jobs.internet.com

internet.commerce
Partners & Affiliates
















RSS Feeds

RSSAll

RSSVC++/C++

RSS.NET/C#

RSSVB

See more EarthWeb Network feeds

Home


The Mists of Avalon
Part 1: A First Glimpse Through the Fog
Rating:

Guido Stercken-Sorrenti (view profile)
July 25, 2005

Environment:  Windows XP SP2, Visual Studio 2005 Beta 2, WinFX SDK Beta 1

Go to page: 1  2  Next

This article introduces "Avalon," the exciting new presentation layer of the upcoming Windows version (codenamed Longhorn). I'll first point out what's so fundamentally new and advantageous about the way Avalon deals with graphics, and then show you how to use XAMLPad, a tool that comes with the WinFXTM SDK, to get a first taste of Avalon programming.


(continued)



In the following parts of this article series, you will see how to use Avalon with .NET code in Visual Studio 2005, and also take a look at the more advanced features of Avalon, such as 3D graphics, animation, and speech.

Many think of Avalon as a future technology and part of Longhorn (which is correct), and hence not yet available (which is wrong): The Beta 1 preview is available to the general public for download (the latest version is of May 2005), and by installing the latest WinFXTM SDK, Avalon applications can be developed with the Visual Studio 2005 Beta 2, which is freely available as well. In fact, many software vendors and individual developers are already busy creating Avalon applications on the current Beta platforms, so they are ready when Longhorn is released.

Note: This article is based on pre-release information from the current WinFXTM SDK Beta, so details might still change. This article will be updated as the WinFXTM SDK gets stable and more details are available.

The Old World: Same Procedure as Every Year...

If you have been developing Win32 applications in C or C++ so far, you will most probably be familiar with the GDI (Graphics Device Interface)—Microsoft Windows' API for device-independent graphics output since 1985. Ever since, the GDI was based on the metaphor of a virtual canvas (the Device Context, or DC), a set of drawing tools like brushes, pens, fonts, bitmaps, and so forth (known as GDI objects) that you could select into a DC in order to use them with the drawing functions (MoveTo, LineTo, Rectangle, Ellipse, TextOut, and so on). The GDI supports basic coordinate translation and scaling, so you could use logical units (like millimeters, inches, twips, or even your own units) for drawing, and have the GDI map them to physical (or device) units, achieving a fair degree of device independence. Ideally, the same drawing code could be used for output to the screen, a printer, or a plotter.

Other Graphics APIs

Just for the sake of completeness: When talking about Windows graphics APIs, the GDI+ (a modernized, more object-oriented revamp of the GDI), OpenGL (an open, multi-platform standard for high-performance 3D graphics, used mostly in scientific visualization and games) and DirectX (an API for direct access to graphics hardware, among others) should not pass unmentioned—all three are alternative, but, with regard to the GDI, much less used graphics APIs available under Win32.

Procedural Drawing

In any case, drawing with the GDI has always been a procedural (or imperative) activity: You wrote code in your favorite language (most probably C or C++, because Visual Basic doesn't directly support GDI calls) and told the GDI, step by step, what to do to get your GUI to look the way you want. It's somewhat like standing next to an artist and giving her instructions:

"Please pick up the blue pen—no, the thick one."

"Okay, now draw a horizontal line across the canvas, at about one third of the canvas height from the top border—leave a margin of half an inch to the left and right."

"Fine. Now put down the blue pen, and pick up the bright red one."

"With that pen, please draw a circle with a bounding rectangle that starts at 4.57 inches from the left and 3.2 inches from the top, and a radius of 2 inches."

"Okay, now take the yellow brush..."

Sounds tedious? It is, but that's the way procedural drawing works (and if you forgot to put down the blue pen, you were eventually arrested by the GDI resource police for stealing pens, and punished with a system crash...). The good news about procedural drawing is that it is flexible; for example, the instruction in the above example "one third of the canvas height" can be easily expressed as an arithmetic construct in any programming language—and hence, the actual position of the line can be made dependent on the current height of the canvas (your window's client area). This is what a typical WM_PAINT handler in Win32 SDK code could look like (it just draws a horizontal line at one third of the client area's height, leaving a margin of 30 pixels to the left and right, and using a blue, four-pixel-wide pen:

case WM_PAINT:
  {
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hWnd, &ps);

    // Get our canvas size:
    RECT rcClient;
    GetClientRect(hWnd, &rcClient);

    // Vertical position is at one-third of the height:
    int lineYPos = (rcClient.bottom - rcClient.top) / 3;
    int margin = 30;

    // Create and select blue pen
    HPEN hBluePen = CreatePen(PS_SOLID, 4, RGB(0, 0, 255));
    HGDIOBJ hOldPen = SelectObject(hdc, hBluePen);

    // Draw the line
    MoveToEx(hdc, rcClient.left+margin, lineYPos, NULL);
    LineTo(hdc, rcClient.right-margin, lineYPos);

    // Clean up...
    SelectObject(hdc, hOldPen);
    DeleteObject(hBluePen);
    EndPaint( hWnd, &ps );
  }
  break;

What's more, you can use conditional statements (in the case of an error message, use red color for the text; otherwise, black) or loops (you can draw a grid, say, a checker board, by drawing lines or squares in two nested loops, calculating the coordinates from the loop indexes). So, although flexibility is the major advantage of procedural drawing, one of the drawbacks is certainly that it requires you to break down the entire drawing code into fine-grained steps—everything needs to be said explicitly and in great detail.

Now, how would it be if, instead of giving step-by-step instructions, you could simply provide a sketch of the drawing, and have the artist elaborate on that? You could even decide about how detailed the sketch would be—either make the sketch rather... well, sketchy, and let the artist put her creativity into the details of execution, or, on the other end of the spectrum, provide a very detailed sketch and leave little room for interpretation. Like the idea? Then, welcome to the world of declarative graphics programming!

Declaration of Independence

The declarative approach is, to some extent, the exact opposite of the procedural one: Instead of specifying how you want something to be done, you rather specify what you want as a result, and leave it up to the executing instance how exactly it fulfills your request. A familiar example of a declarative description is a Web page that you might design in HTML (HyperText Markup Language): You define the logical structure of your document, including headers, sub headers, paragraphs, tables, emphasized text, and the like, but it is up to the browser on the client side how exactly the page will be rendered. If you like, you can of course get into more detail and also specify font sizes, positions, and exact spacing for table cells—the point is that you can, but need not be so explicit.

In the IT world, we encounter the dualism between the procedural and the declarative paradigm all over the place. For example, a macro in Excel (which typically consists of instruction sequences, like "select a range of cells, copy them, move the cell cursor to another place, paste...") is procedural. An Excel formula, OTOH, is declarative: You just specify that you want the sum of a range of cells, divided by the number of months to appear in the cell where you put the formula, and leave it up to the spreadsheet's calculation engine how, and, more specifically, in which order to perform the calculation steps that lead to the desired result. By the way: The declarative nature of spreadsheet formulas has been one of the major reasons for the enormous success of spreadsheet applications like VisiCalc, Lotus 1-2-3 and later Excel, because they allowed users to create solutions tailored to their needs without having to learn how to program. To non-programmers, it is much more natural to specify what they want instead of explaining step by step how they want it to be done.

Almost all of the more widely used programming languages are imperative—two prominent exceptions being Prolog and LISP, which are both declarative languages.

Note: As with most dualisms, there is no hard dividing line between "procedural" and "declarative;" some approaches are more procedural (they usually rely more on code) whereas others are more declarative (which normally means less code and more data). One of the main advantages of the latter is that it is much easier to build editors and other tools for declarative data—but I'll come back to that in a moment.

Introducing Avalon

Okay, now where and how does Avalon come in? "Avalon" is the codename for the presentation subsystem of WinFX, an extension of the .NET 2.0 Framework, and the new application programming model for the upcoming release of the Windows OS, currently only known as "Longhorn." Longhorn's release to the market is scheduled for mid 2006, and plans are to make WinFX available for Windows XP and Windows Server 2003 as well in early 2006.

For those of you interested in trivia: "Avalon" is the name of a legendary island somewhere in the British Isles. According to the legend, it's the place where King Arthur's body is buried. The title of this article refers to Marion Zimmer Bradley's novel, The Mists of Avalon, which tells the King Arthur myth from a feminist point of view. However, Avalon is also the name of a peninsula in Newfoundland, and that's probably where the name for the Avalon subsystem comes from: Recently, Microsoft tends to use names of geographical locations in the American North-Pacific as codenames for upcoming products and technologies. By the way, "Longhorn" is a saloon in the Whistler-Blackcomb ski resort near Vancouver, and both "Whistler" and "Blackcomb" are codenames as well (for XP and Longhorn Server, respectively). Guess where the Microsoft OS guys hold their design retreats...

Because "Avalon" is a codename, Microsoft puts it in quotation marks in most of its publications. For the sake of simplicity, I will omit the quotation marks for the rest of this article.

The Three Pillars of WinFX

Applications taking advantage of WinFX rest on three subsystems, often referred to as the pillars of WinFX: Avalon (the presentation layer), WinFS (file system and data services), and Indigo (communication services):

Although Avalon and Indigo will be included in the Longhorn Beta 1 announced for summer 2005, WinFS didn't make it and will be added later. This article series focuses on Avalon, the leftmost pillar.

All the capabilities of Avalon are exposed through a managed object model that can be manipulated from any language that supports the CLR (Common Language Runtime). The current Beta 2 of Visual Studio 2005 only allows C# and Visual Basic for creating WinFX applications (so much for a "common" language...)—hopefully, the final release will support C++ as well.

We will soon start to be seeing applications with very fancy and impressive Avalon user interfaces, so it's probably a good idea for developers to get prepared for the new world of UI programming as early as possible (that's precisely why I wrote this article—and probably also the reason why you are reading it).

A major difference between Avalon and the GDI is—you will have guessed it by now—that Avalon uses a declarative model to describe graphic entities of any kind: Windows, Web pages, layout panels, vector graphics, reusable controls, animations, 3D objects, and sceneries.... Everything can be built in a declarative manner.

The Object Tree

Graphics output in an Avalon application is not achieved by a series of sequential instructions, but rather by providing a hierarchy of objects, along with their properties, from the Avalon class model. So, instead of saying "pick up a three-pixel-wide red pen, pick up a yellow, solid brush, draw a circle using the current pen for the border and the current brush to fill it," you would rather say: "We have a window. The window contains a canvas. On the canvas, there is a circle. Ah, and yes, the circle's border is red, and it is filled in yellow. You want to know how thick to draw the border? Three millimeters—unless otherwise specified."

Any graphics scenario in Avalon is constituted by a hierarchy of objects from the Avalon object model: the object tree.

A very simple object tree might be depicted like this:

At the heart of Avalon, there is a compositing, vector-based rendering engine that takes full advantage of the hardware capabilities of the installed graphics adapter (allowing for effects like free scaling, 3D shading, transparency, alpha blending, specular reflection, animation, video, and so forth) to interpret the object tree and render the scenario. However, let's approach it slowly: No 3D, no animation here for the moment: This is what the output might look like when the above object tree is rendered:

In addition to simple geometrical shapes, the Avalon class model includes all sorts of controls like edit boxes, labels, buttons, combo boxes, checkboxes, list controls—everything you now know from MFC or Windows Forms, and much more. However, all those controls are defined as vector graphics—so instead of getting "jagged" when resized, they scale nicely to every possible screen resolution and size. Avalon is mainly vector-based (I say "mainly" because bitmaps and video movies, which are pixel-based, can be integrated as well).

Essentially, the UI of an Avalon application can be built by creating an object tree of GUI elements. In that case, the object tree is often referred to as a UI tree.

A simple UI tree might be depicted like this:

When rendered by the Avalon rendering engine, the output might look similar to the following:

Because all the UI elements are vector-based, the window containing them can be easily resized, and the controls will grow and shrink or rearrange accordingly. Styles can be applied at any level, changing, for example, the font used for all elements, or just the border color of certain buttons.

Even data binding can be added in a declarative manner: You can associate certain controls with data sources like an SQL database or RSS feeds, and when it comes to displaying the controls, the contents will be automatically supplied from those sources—without writing a line of procedural code!

You can create and modify an object tree (or, more specifically, a UI tree) in much the same way you deal with other .NET objects: by using any CLR compliant language (like C++, C# or Visual Basic) to instantiate objects from the .NET class library, setting their properties, and calling their methods. Now, you might wonder where the benefit is, and why all the fuss about declarative drawing? After all, you still need to use a programming language and lastly call procedures to get something displayed.

Hold on—there's more to it. Programmatically creating the UI tree is just one way of doing it (and I will discuss it in an upcoming article). The other is... XAML.

Meet XAML

XAML (pronounced "zammel") is a markup language based on XML that can be used to build an Avalon object tree. XAML is short for eXtensible Application Markup Language. (Surprisingly, the "A" in XAML doesn't stand for "Avalon," but for "Application:" That's because in the future, we won't only be using it for describing Avalon scenarios, but .NET object hierarchies in general. Keep this in mind—one day, you will understand the impact of this statement.)

The following XAML code represents a UI tree and will produce the output shown above:

<Page xmlns="http://schemas.microsoft.com/winfx/avalon/2005"
      Name="Page1">
  <DockPanel Background="Bisque" Name="OuterPanel">

    <StackPanel  Background="LightBlue" DockPanel.Dock="Top"
                 Margin="10,10,10,10">
      <TextBox   HorizontalAlignment="Left"
                 Height="24px"
                 Width="2.6 cm"
                 Margin="20,10,10,10">Text selection</TextBox>

      <Button    HorizontalAlignment="Left"
                 Height="30px"
                 Width="100px"
                 Margin="20,10,10,10" Name="Button1">Copy</Button>
    </StackPanel>

    <Label VerticalAlignment="Top">Select Country:</Label>
    <ComboBox VerticalAlignment="Top"
              Height="24px"
              Width="100px">
              IsSelectionRequired="True">
      <ComboBoxItem>France</ComboBoxItem>
      <ComboBoxItem>Germany</ComboBoxItem>
      <ComboBoxItem>Italy</ComboBoxItem>
      <ComboBoxItem>USA</ComboBoxItem>
    </ComboBox>
  </DockPanel>
</Page>

The XAML tags correspond directly to the objects in the UI tree, with attributes describing their properties, and the tag data representing the textual content of the visual elements. For example, the following Label tag maps to a Label object with the VerticalAlignment attribute set to "Top"and with "Select Country:" as the content, which is the textual representation that the users will see:

<Label VerticalAlignment="Top">Select Country:</Label>

Panels

Panels have no text content of their own: They are rectangular containers for other elements (like text blocks, buttons, controls—and other panels). Panels come in seven flavors, all with their own specific layout properties: BulletPanel, Canvas, DockPanel, Grid, StackPanel, TabPanel, and ToolBarOverflowPanel. Panels can be deeply nested to obtain a very fine-tuned, yet flexible, layout. If that reminds you of tables in HTML, you're only partially right: HTML tables were originally introduced to provide a logical structure for tabular data, arranging it in tables, rows and cells; however, tables have ever been misused by Web page designers for layout purposes, leading to countless problems with the way tables were interpreted and displayed by different browsers. In contrast, Avalon panels have been designed with layout in mind—and by choosing which level of detail you specify as the attributes for panels (like absolute sizes or margins), you can decide to which degree the layout should be fixed or free-flowing depending on the run-time requirements. In short: Avalon panels are meant to do what HTML tables have been long misused for—and much more.

Of course, there are corresponding XAML tags for all the other types of controls from the Avalon class hierarchy: buttons, text boxes, combo boxes, list controls...

Dialog Resources

"But wait," I hear you say, "that way of describing a user interface reminds me of dialog resources in classical Win32 SDK and MFC applications!" And again, you're partially right. Indeed, dialog resource templates have been a strong declarative component in classical Win32 applications (which I've left—purposefully—unmentioned in my introduction about procedural UI design). Instead of writing code for creating a dialog box and adding child controls to it, you could "draw" parts of your UI in a resource editor. At run-time, Windows would create the resulting dialog window with all child controls for you and handle a lot of stuff automatically:

  • Dialog resource templates are designed using "dialog units"—virtual units that are appropriately transformed to device units (pixels) at run-time, depending on the system base font size that the user had selected in the "Display" control panel.
  • The background of dialog windows is painted automatically, again according to system-wide settings the user made.
  • Certain keys (like tab or arrow keys) are automatically handled according to the tab order and geometrical layout specified at design time.

Resources and Localization

Look for a moment at the motivation behind all this: The resource concept has been invented (not by Microsoft, by the way, but by Apple when they first introduced Lisa, the predecessor of the Macintosh, in 1983) to simplify the localization of applications to different countries and languages (now fancily called "cultures" in .NET-speak). An obvious first step is to put any text a user would see not as hard-coded strings into the program's source code, but to keep it in a special data section in a well-defined format so that it could easily be extracted and modified from a compiled executable by using appropriate tools (resource editors or more specialized localization tools); the idea was to be able to translate every textual element of an existing application without having to modify the source code. It soon became obvious that merely translating text strings only did half the job: Text differs significantly in length between various languages. For example, French text is 30% longer in average than the corresponding English text. A button labeled "Open File" would become "Ouvrir fichier" in French; that's 14 characters instead of 9 (a 55% gain!), and chances are good that a button designed to hold the English text would be too short for the French translation. In Italian, it would be "Aprire archivio" (+66%), and Finnish or Hungarian texts are usually even longer. That's why the resource concept was soon extended to entire dialogs and their layout: Now translators, instead of merely translating text, could use tools to adjust the layout of dialogs and the sizes of controls so that the translated text would fit nicely. By the way, similar ideas led to bitmaps and icons ending up in resources as well: Certain pictograms or visual representations of objects (and even colors) can have different meanings in different cultures.

However, the concept of resources ends with menus and dialog boxes: The central parts of the UI of most applications need to be much more flexible than dialog resources allow for, and typically can't be built with a resource editor, but have to be coded procedurally, creating controls and child windows by appropriate API calls, and, as mentioned at the beginning of this article, by drawing significant parts of the UI with procedural GDI calls. Needless to say, that kind of code uses either hard-coded strings and fixed element positions (and hence those applications are impossible to localize with a resource editor), or have to be coded in an extremely flexible way, loading any user-visible text from string table resources, and making the size of procedurally created UI elements depend on the actual text length at run-time. I know, because you are all conscientious developers, you will say "So what; that's the way I've learned it and always done it—of course I keep all my strings in resources!" Heck, of all real-world Windows projects I've seen do far, only about 5% were coded by the textbook. The remaining 95% used hard-coded strings and fixed element positions, making them impossible to localize without modifying the source code.

In other words: A high ridge went through the UI code in classical Win32 applications: On one side, you had the parts designed as resources (declarative!) that were easy to create and localize and had many aspects handled automatically at run-time, and on the other side, the parts that required more fine-tuned control by the developer and hence were coded procedurally—either requiring an enormous extra effort to keep them flexible enough for localization, or completely neglecting that requirement.

But where did I leave off before talking about resources? Ah, Avalon. Its declarative nature makes an important difference in several aspects: Instead of limiting itself to certain trivial and mundane parts of the UI like menus, dialog boxes, and accelerator keys, almost the entire UI of an Avalon application can be designed in a declarative way! This leads to a couple of advantages:

To summarize, the real power of XAML in Avalon applications is based on two different levels of abstraction: The first is the abstraction of the business logic (usually written in procedural code-behind) from the visual representation supplied declaratively in XAML (which separates logic from presentation), whereas the second level is the abstraction of the text content from the visual representation, separating design from content and hence allowing for easy localization and data binding.

XAML in .NET Applications

When you create an Avalon application with XAML, one or more files with XAML code will be included in your Visual Studio project, and get compiled to a binary format (BAML) which is added to your assembly as a resource.

An important thing to note is that with XAML code it is not only possible to describe a static scenario (like HTML, Postscript, or GDI Metafiles), but include dynamic effects like animation and even event handling code (more like DHTML or HTML with embedded VBScript or Jscript). If you are familiar with ASP, you will know the idea of code-behind files—actually, a similar concept is normally used with XAML, where the XAML file is compiled to a partial .NET class, and additional .NET code that you can supply will handle the aspects of the GUI which are not described in XAML.

Actually, the comparision to HTML is not so bad: Creating a user interface in XAML is very similar to building a Web page in HTML. However, XAML goes far beyond the capabilities of HTML in that it adds very advanced 2D and 3D vector graphics, storyboard- and timeline-based animation, data binding, event handling and speech recognition and synthesis.

About the Author
Guido is a freelance software developer and consultant, specializing mainly in graphics software and UI design, and has been using Visual C++, MFC and the GDI for more than ten years. As a regular contributor to the CodeGuru forums, he has been awarded MVP (Most Valuable Professional) by Microsoft in 2005 and 2006. He currently spends much time exploring Avalon, the new graphics subsystem of the future Windows platforms.

Go to page: 1  2  Next

Tools:
Add www.codeguru.com to your favorites
Add www.codeguru.com to your browser search box
IE 7 | Firefox 2.0 | Firefox 1.5.x
Receive news via our XML/RSS feed







RATE THIS ARTICLE:   Excellent  Very Good  Average  Below Average  Poor  

(You must be signed in to rank an article. Not a member? Click here to register)

Latest Comments:
How to provide 3D effect to UI controls like Button,Textbox. - Enigmatic (03/01/2006)
very good article - naveenl (12/16/2005)
hhhh - hungvn (10/23/2005)
very nice - vinay pandey (09/27/2005)
very nice - Alin (07/26/2005)

View All Comments
Add a Comment:
Title:
Comment:
Pre-Formatted: Check this if you want the text to display with the formatting as typed (good for source code)



(You must be signed in to comment on an article. Not a member? Click here to register)


JupiterOnlineMedia

internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info


Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers