Friday, July 8, 2011

Setting up MongoDB on OSX

Recently I successfully downloaded and installed MongoDB on my mac. I am a Windows developer dwelling in the world of linux programming, so I wanted to blog about my experience as it may be helpful to other fellow devs who are new to linux as well.

Most of the steps below are refinement / explanation of http://www.mongodb.org/display/DOCS/Building+for+OS+X
  • Step 1 - Download MongoDB server - From mongodb.org website download MongoDB server and untar the files in some folder (MongoDB_Server).
  • Step 2 - Create a folder /data/db in your root. MongoDB server uses this path to store the database(s).
  • Step 3- Download MongoDB client - From mongodb.org download a compatible client (same version as the server) and untar the files in client folder (MongoDB_Client)
  • Step 4 - If you haven't done so far, you must download package manager on OSX called homebrew. A package manager on linux is an application that makes it dead simple to download other applications and install them on your system. To download homebrew open a shell window and type: curl -L http://github.com/mxcl/homebrew/tarball/master | tar xz --strip 1 -C /usr/local
  • Step 5 - Download boost C++ library - Execute: brew install boost
  • Step 6 - Download scons (Makefile executor) - Execute: brew install scons
  • Step 7 - Download pcre++ (Perl regular expression lib) - Execute: brew install pcre++
  • Step 8 - Build client - Navigate to the client folder and simply type: scons
  • Step 9 - Start server - Open a new shell window and navigate to server folder's bin subfolder and type: mangod. This should start the server !
  • Step 10 - Test client - Navigate to client folder and execute: ./clientTest (this should run a simple client test)
  • Step 11 - Write your own test: In the client folder's client/example subfolder, create a test program with code from: http://www.mongodb.org/pages/viewpage.action?pageId=133415 and name it test.cpp
  • Step 12 - Now navigate to root client folder and execute: g++ -o test client/examples/test.cpp -I mongo -L. -lmongoclient -lpthread -lboost_thread-mt -lboost_filesystem-mt -lboost_system-mt
  • Step 13: Last step should compile your code and output test binary. Simply execute this binary to verify client code ! Ensure that your server is running all this time...


Sunday, May 1, 2011

My favorite WPF book of all times–WPF Control Development Unleashed

 

Whenever I pick up a technical book to acquaint myself with a particular technology I personally look for the philosophy which makes that particular technology relevant in the field. After all if you just want an introduction or code samples, internet is a valuable resource why bother buying a book, right?

About an year and half ago I was put in-charge of UI design of our product using Windows Presentation Foundation (WPF) and started looking out for resources on the web, in the libraries and books. I finally stumbled upon this masterpiece by Pavan Podila and Kevin Hoffman called WPF Control Development Unleashed.

I really loved how the book introduces the philosophy of WPF UI design and the diverse visual class structure in the opening chapters. Most admirably how authors provide insight and emphasis into code reuse, UI templating, extending existing controls using attached properties before jumping on to custom controls. In fact many examples in the book illustrate how extending existing UI controls result in more maintainable code without much effort.

The book covers a very broad spectrum of UI development in WPF such as building custom panels, UI virtualization, advanced scrolling, 2D and 3D animations, pixel shader effects and even rare topics such as UI automation which are skipped in many other books I have read. The book is pure joy to read and I have personally read this book about three times if not more.

I have been successful in applying concepts from the book into our product – BlackBerry Desktop Software, and so have my team. I highly recommend this book for any serious WPF developer who can gain end to end insight into the technology from this fabulous resource.

Sunday, January 30, 2011

MixModes Synergy Toolkit for Windows Phone 7

Synergy is a platform toolkit that unleashes the power of WPF, Silverlight and Windows Phone 7 platforms. In this blog I will discuss the Windows 7 phone part of this library and how it helps to somehow converge development practices to that of WPF and leverage data binding capabilities.

Synergy toolkit can be accessed at its codeplex home where Santa (myself) keeps delivering new gifts and wishes everyday. I have released v1 of Windows Phone 7 library in the downloads section.

For a background on WPF synergy toolkit, you can refer to my previous blog here. I also wrote a docking windows framework in WPF edition of synergy that you can refer here and a window theming article here.

You can follow me on twitter @ashishkaila

Without further adieu let me walk you through the features of the v1 release.

Base Framework for Windows Phone 7 Development

Commanding Support

CommandBase class provides a flexible implementation for custom commands. This class works on an Action<object> instance for command invocation and an optional Predicate<object> for command execution evaluation. If the predicate is not specified, it is assumed that command can be executed anytime. Simply speaking, one can instantiate CommandBase class as follows:

CommandBase myCommand = new CommandBase(arg=>Foo(arg), arg=>CanFoo(arg));

Moreover since WP7 and Silverlight do not provide out of the box capability to bind

Dependency System Enhancements

Several enhancements in dependency system have been provided that helps developers tap easily into the framework for advanced operations related to binding and dependency properties. These enhancements are as follows:

Observable Binding

ObservableBinding class as the name suggests observes a binding for value changes and provides the most recent value for the binding. This class is very useful within custom behaviors and trigger actions where data context of associated object does not propagate to these entities. This is so because Behaviors and Triggers are attached properties within the static Interaction class (declared in System.Windows.Interactivity assembly) and are therefore detached from the dependency system.

By declaring a dependency property of type Binding and using ObservableBinding within a Behavior/TriggerAction you can both hook into the dependency property system of associated object as well as evaluate the most recent value of the binding.

For instance EventToCommand trigger action defines a dependency property Command of type Binding:

public static DependencyProperty CommandProperty = DependencyProperty.Register("Command",
                                                                                       typeof (Binding),
                                                                                       typeof (EventToCommand),
                                                                                       new PropertyMetadata(null, OnCommandChanged));

It also declares an ObservableBinding for the command:

private readonly ObservableBinding _observableCommandBinding = new ObservableBinding();

This _observableCommandBinding member will provide us with the latest value of Binding exposed by Command property.

There are certain rules to ensure that ObservableBinding works as expected for Binding properties. Basically anytime Binding property changes, we have to unhook from the old Binding and hook into the new binding. This is done in the OnCommandChanged method which is called when Binding property is changed (that is the actual Binding property and not the value of the Binding):

private static void OnCommandParameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    EventToCommand eventToCommand = d as EventToCommand;

    if (eventToCommand == null)
    {
        return;
    }

    eventToCommand._observableCommandParameterBinding.Detach();
            
    if ((e.NewValue != null) && (eventToCommand.AssociatedObject != null))
    {
           eventToCommand._observableCommandParameterBinding.Attach(eventToCommand.Command eventToCommand.AssociatedObject);
    }
}

Also when associated object is initially attached to the TriggerAction / Behavior, we need to attach to the ObservableBinding:

protected override void OnAttached()
{
    base.OnAttached();

    if (Command != null)
    {
        _observableCommandBinding.Attach(Command, AssociatedObject);
    }
}

If you skip the above step, the initial value of Binding will not be tracked by ObservableBinding.

ObservableDependencyProperty

ObservableDependencyProperty on the other hand provides the ability to track changes in dependency property declared in another DependencyObject by way of event notifications. The constructor of ObservableDependencyProperty takes two parameters: the string representing the name of the dependency property to observe  and a delegate of type DependencyPropertyChangedEventHandler that will be called when the dependency property changes:

ObservableDependencyProperty _verticalScrollChange = new ObservableDependencyProperty("VerticalOffset", OnVerticalScroll);

To track changes in dependency property of the actual DependencyObject, ObservableDependencyProperty instance must be attached to it via AddValueChanged method:

_verticalScrollChange.AddValueChanged(_scrollViewer);

Similarly to detach or stop property change tracking, RemoveValueChanged method may be called:

_verticalScrollChange.RemoveValueChanged();

Complete MVVM Framework

Custom view models can be implemented by simply inheriting from the base class ViewModelBase. To raise PropertyChanged event, a type safe RaisePropertyChanged method can be called with an expression containing your property reference, e.g.:

RaisePropertyChanged(x=>MyProperty);

ViewModelBase also contains a Navigate method that can navigate the phone to a bound view performing data binding behind the scenes (more on this in the next section), e.g.:

MyViewModel viewModel = new MyViewModel();
viewModel.Navigate(); // Note: For this to work, your application must inherit from PhoneApplication class (see below)

Easier Navigation via Declarative View-ViewModel Bindings

In WPF DataTemplates could bind a ViewModel to View on an application level. This binding enabled runtime view generation within ContentPresenter. I wanted to extend the same idea to Windows Phone 7 screen navigation since url based navigation within an application seems error prone and passing query parameters is tedious.

ViewSelector class provides this declarative binding capabilities in conjunction with ViewBinding class. Basically in your application resources you can define this mapping:

<Framework:ViewSelector x:Key="ApplicationViewSelector">
    <Framework:ViewBinding ViewModelType="INameU.ViewModels.NameListViewModel"
                                                           ViewUri="/Views/NameListView.xaml" />
    <Framework:ViewBinding ViewModelType="INameU.ViewModels.NameDetailViewModel"
                                                           ViewUri="/Views/NameDetailView.xaml" />
</Framework:ViewSelector>

where Framework is mapped as:

xmlns:Framework="clr-namespace:MixModes.Phone.Synergy.Framework;assembly=MixModes.Phone.Synergy"

Once you have done this, you can call the Navigate method from your ViewModel instance to navigate to the mapped view and data binding to it at the same time, without using any url(s) !

DockPanel and WrapPanel Controls

I have ported both DockPanel as well as WrapPanel from Silverlight Toolkit for Windows Phone 7 so you do not have to reference the toolkit if you are not using any additional functionality other than these panels.

EventToCommand TriggerAction

A common pain point is the absence of Command and CommandParameter properties on controls such as Button and ListBoxItem. To fill this gap EventToCommand trigger action can be used to map a RoutedEvent to an ICommand instance along with a CommandParameter instance. To bind the RoutedCommand to EventToCommand trigger you need to add the trigger to the associated framework element:

<Button Content="Click Me">
    <Custom:Interaction.Triggers>
        <Custom:EventTrigger EventName="Click">
            <Triggers:EventToCommand Command="{Binding Path=DataContext.ShowDetailsCommand, ElementName=Page}"
                                     PassEventArgsToCommand="True"/>
            </Custom:EventTrigger>
        </Custom:Interaction.Triggers>
</Button>

PassEventArgsToCommand property when set to true, passes the RoutedEventArgs as CommandParameter to the associated ICommand’s Execute method.

ScrollLoadBehavior

ScrollLoadBehavior allows asynchronous loading of data when user scrolls a scroll viewer vertically to the bottom. ScrollLoadBehavior has an associated ICommand and CommandParameter that are executed anytime scroll viewer reaches its bottommost point. Loading is detected via ICommand’s CanExecute method. For example:

<ListBox DataContext="{Binding}"                
         ItemsSource="{Binding Path=Names}">
    <Custom:Interaction.Behaviors>
        <Behavior:ScrollLoadBehavior Command="{Binding Path=LoadNamesCommand}" />
    </Custom:Interaction.Behaviors>
</ListBox>

Notice the explicit DataContext=”{Binding}” in the ListBox. This is necessary as without explicit parent data binding, ItemsSource sets the DataContext to its value thereby failing the binding for ScrollLoadBehavior.

Out Of The Box Converters

Many frequently used out of the box converters have been provided in the toolkit:

  • EnumMatchConverter – Matches a value of enum member with a constant value and returns boolean indicating the match. For example, if you want to enable a control when the state is StateEnum.IsError, you can do the following:
    Enabled="{Binding Path=State, Converter={StaticResource EnumConverter}, ConverterParameter=IsError}"
  • NotConverter – Inverts the value of a boolean expression.
  • VisibilityConverter – Based on a boolean value, shows (if value is true) or collapses (if value is false) visibility of a control
  • PipeConverter – Pipes a value through multiple converters to compute the end value of the binding expression. For example if you want to match a value to enumeration member “Loading” and then determine the visibility of a control you could declare a pipe converter as follows:

    <conv:PipeConverter x:Key="LoadingMessageVisibilityConverter">
        <conv:EnumMatchConverter />
        <conv:VisibilityConverter />
    </conv:PipeConverter>

    The values are piped from top to bottom, hence first EnumMatchConverter is invoked and then VisibilityConverter. To use it simply refer to the PipeConverter as follows:

    Visibility="{Binding Path=State, Converter={StaticResource LoadingMessageVisibilityConverter}, ConverterParameter=Loading}"
  • ThemeBasedResourceConverter – This converter returns resources based on the theme of Windows 7 Phone (either dark or light). To use this converter one needs to point to both theme resources via LightThemeResource and DarkThemeResource properties. For example if your application has navigation button images for both themes as NavigationLight.png and NavigationDark.png, you could use ThemeBasedResourceConverter to set the appropriate image as the background of a button as follows:

    <phone:PhoneApplicationPage.Resources>
        <Converters:ThemeBasedResourceConverter x:Key="ThemeBasedResourceConverter"
                                            LightThemeResource="../Resources/NavigationLight.png"
                                            DarkThemeResource="../Resources/NavigationDark.png" />
    </phone:PhoneApplicationPage.Resources>

    And then refer to the above ThemeBasedResourceConverter in the button:

    <Button>
        <Image Stretch="None"
               Source="{Binding Path=., RelativeSource={RelativeSource Self}, Converter={StaticResource ThemeBasedResourceConverter}}">
        </Image>
    </Button>

So that’s all in v1 folks. I will be happy to receive any feedback you may have and will continuously develop Synergy toolkit to make your development easier whether you code in WPF, WP7 or Silverlight !

Saturday, January 1, 2011

Automate your UI using Microsoft automation framework

UI automation is a programmatic interface to the user interface of your application to external applications that may be interested in programmatic communication with your UI. In fact UI automation is the prime facilitator for accessibility features in Windows where external applications such as screen readers that have no clue about your application, can still interact with your application easily.

I was acquainted with UI automation during my tenure at Microsoft in 2005 when I started working as software developer in test within Visual Studio Team Architects team on a project called Whitehorse. For those who need some background, Whitehorse consisted of SOA diagrams within Visual Studio (you can learn more about this project in the MSDN magazine here). Testing of visual designers in the product test team was done entirely using an internal UI test automation framework built on top of Microsoft Active Accessibility framework.

The UI automation framework is relatively new to Windows platform and successor to Windows Active Accessibility. The framework provides a unified way to discover UI controls in an application built using any of the following desktop technologies: Win32, Windows Forms or WPF.

UI automation has several benefits when used in applications:

  • Accessibility features – UI automation provides accessibility support in your application. Accessibility support becomes even more important when there are matter of legal compliance in the domain your application is used in (e.g. Government regulations).
  • Automated UI testing – UI automation can automate testing for application UI saving time and costs associated with manual and regression testing. Moreover given a set of use cases, UI automation can be used to verify application behavior via scenario tests.
  • Custom controls – If you are authoring custom controls, UI automation support enables end clients of your control to automate your control in their application UI.

How does UI automation work?

UI automation provides a common protocol for exchanging information between your application and an external entity such as screen reader or automated UI tests. UI automation provides an API using which an external application can discover controls, navigate the visual tree, access the state of the controls and perform control specific actions.

In WPF, automation object model is provided via System.Windows.Automation.AutomationElement instance associated with a UIElement (said to be “automation peer” of the control). If you are authoring a custom control, you may want to implement one or more interfaces defined in the UIAutomationProvider.dll under the System.Windows.Automation.Provider namespace to support UI automation.

To support UI automation, a control author needs to implement an abstract class AutomationPeer from UIElement class’ virtual method OnCreateAutomationPeer. AutomationPeer  is then used at runtime to extract AutomationElement for the UIElement. It is important to note that the standard controls in WPF have standard implementation of AutomationPeer associated with the controls out of the box. In authoring a derivative of AutomationPeer you may want to subclass a standard implementation rather than deriving directly from AutomationPeer and authoring a class from scratch.

Following image shows out of the box derivatives of AutomationPeer:

image

Each AutomationPeer must implement one or more “standard control patterns” to expose capabilities that can be used by automation clients such as screen readers. A control may expose one or more control patterns defined by the members of PatternIntern enumeration:

image

A control can be queried for a specific PatternInferface via AutomationPeer’s GetPattern method that takes PatternInterface member as a parameter and returns the supported pattern – a derivative of BasePattern or null if the specified PatternInterface value does not correspond to a supported pattern.

image

BasePattern has several out of the box derivatives that target standard control patterns:

image

For example Button, Hyperlink and MenuItem controls support InvokePattern and can therefore indicate to the automation clients that control is capable of invoking a command. Similarly an expander control supports ExpandCollapsePattern to indicate that control is capable of expanding or collapsing content within it.

Control patterns are strictly limited and custom control patterns are not supported. The reason is that automation clients must work on a standardized protocol and cannot interpret custom patterns to figure out the functionality of the controls.

Since UI automation is optional in WPF, you may tag on automation properties on a control via attached properties specified in the AutomationProperties static class:

image

For example if we want to specify automation id on a text box we could specify it as following in XAML:

<TextBox Text=”{Binding Telephone}” AutomationProperties.Id=”ID_TXT_TELEPHONE”/>

Navigating the automation tree in WPF

Similar to visual tree navigation, one can navigate UI automation tree in WPF using the AutomationElement instance. However there is an important distinction – unlike the visual tree, an automation tree is not constructed upfront and is only constructed during automation tree navigation. This is so because unlike visual tree, UI automation is optional in applications. There are more than one way to navigate the automation tree depending on the view of automation tree you would want:

  • Raw view – Raw view refers to non-filtered complete automation tree view. Using TreeWalker class’ RawViewWalker property raw view can be navigated.
  • Control view – A control view is a subset of raw view that only contains AutomationElements that correspond to controls (or in other words have their AutomationElement.IsControlElementProperty property set). Using TreeWalker class’ ControlViewWalker property control view can be navigated.
  • Content view – A content view is a subset of control view that only contains AutomationElements that correspond to elements that represent information in terms of content to the end user(or in other words have their AutomationElement.IsContentElementProperty property set). Using TreeWalker class’ ContentViewWalker property content view can be navigated.
  • Custom view – Using a AutomationElement and a condition (which can be one of PropertyCondition, AndCondition, OrCondition or NotCondition) one can navigate automation tree in a custom manner. To navigate a custom view a call to the FirstFind or FindAll methods of AutomationElement is made with a tree scope (TreeScope enumeration specifying the levels in terms of Element, Children, Descendants, Subtree, Parent and Ancestors or any combination of these flags) and a condition.

The root of the automation tree is represented by static property AutomationElement.RootElement refers to the user’s desktop. One can either navigate a automation tree via RootElement or quite often more efficiently from the AutomationElement corresponding to the application window which can be obtained via AutomationElement.FromHandle method by passing in the handle to the application window.

A real world example – automating Windows calculator

As a real world example, let’s author test cases that uses UI automation to test Windows calculator. The aim of the tests is to test the following aspects of calculator:

  • Data entry verification – Validates that a number being typed appears correctly in the calculator
  • Editing options – Validates that copy and paste works as expected in the calculator
  • Calculation validation – Validates given an expression tree, calculator calculates the expression correctly.

You may download the completed example from below:

 

Calculator class

We will start the example by modeling Calculator class which will be our interface to Windows calculator. The calculator class shall fire up an instance of Windows calculator upon construction and shall provide methods to manipulate the calculator. Also this class shall implement IDisposable interface and shall dispose the calculator process upon test conclusion. Clean calculator instance for every test ensures no d

Following is the constructor of Calculator class:

public Calculator()
{
    _calculatorProcess = Process.Start("Calc.exe");

    int ct = 0;
    do
    {
        _calculatorAutomationElement = AutomationElement.RootElement.FindFirst(TreeScope.Children,
                                                                              new PropertyCondition(AutomationElement.NameProperty, "Calculator"));
        ++ct;
        Thread.Sleep(100);
    }
    while (_calculatorAutomationElement == null && ct < 50);

    if (_calculatorAutomationElement == null)
    {
        throw new InvalidOperationException("Calculator must be running");
    }

    _resultTextBoxAutomationElement = _calculatorAutomationElement.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "150"));

    if (_resultTextBoxAutomationElement == null)
    {
        throw new InvalidOperationException("Could not find result box");
    }

    GetInvokePattern(GetFunctionButton(Functions.Clear)).Invoke();
}

The code fires up calculator process and waits for automation element to become available. Then it proceeds to discovering and initializing automation elements that will be used to interact with the calculator. For example to obtain access to calculator result text box we do a lookup of automation id of 150 within the main calculator automation element. Automation Ids of elements were obtained using Spy++ utility that ships with Visual Studio by following the steps below:

  • Fire up a calculator instance and then fire up Spy++.
  • Type any number in calculator (I typed 1234) to identify it within Spy++.
  • Press Ctrl + F3 in Spy++ and from the search window drag the cross bow over to the calculator instance. This will highlight the calculator process in Spy ++.
  • Find the window instance corresponding to the pressed number and click to select it.
  • Right click on the selected window and select Properties menu item to fire up the properties window
  • Look up the control Id in the Property Inspector window. This is the automation id for the control in Hex. Convert it into decimal before using it in code. In my case a hex value of 96 corresponds to 150 in decimal. This is how I got 150 !

image

image

Dispose method simply terminate the process:

public void Dispose()
{
    _calculatorProcess.CloseMainWindow();
    _calculatorProcess.Dispose();
}

To obtain InvokePattern to invoke buttons we use a utility method GetInvokePattern for a specified AutomationElement:

public InvokePattern GetInvokePattern(AutomationElement element)
{
    return element.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
}

AutomationElement for a function button can be retrieved via GetFunctionButton method that takes in string for the function (e.g. “Clear”) as its input:

public AutomationElement GetFunctionButton(string functionName)
{
    AutomationElement functionButton = _calculatorAutomationElement.FindFirst(TreeScope.Descendants,
                                                              newPropertyCondition(AutomationElement.NameProperty, functionName));

    if (functionButton == null)
    {
        throw new InvalidOperationException("No function button found with name: " + functionName);
    }

    return functionButton;
}

All the function names are defined within the Functions static class:

public class Functions
{
    // Functions
    public const string MemoryClear = "Memory clear";
    public const string Backspace = "Backspace";
    public const string MemoryRecall = "Memory recall";
    public const string ClearEntry = "Clear entry";
    public const string MemoryStore = "Memory store";
    public const string Clear = "Clear";
    public const string DecimalSeparator = "Decimal separator";
    public const string MemoryAdd = "Memory add";
    public const string MemoryRemove = "Memory subtract";
    public const string Equals = "Equals";
}

Similarly we query for a digit button using GetDigitButton method that takes digit as an input and returns the associated AutomationElement:

public AutomationElement GetDigitButton(int number)
{
    if ((number < 0) || (number > 9))
    {
        throw new InvalidOperationException("mumber must be a digit 0-9");
    }

    AutomationElement buttonElement = _calculatorAutomationElement.FindFirst(TreeScope.Descendants,
                                                              new PropertyCondition(AutomationElement.NameProperty, number.ToString()));

    if (buttonElement == null)
    {
        throw new InvalidOperationException("Could not find button corresponding to digit" + number);
    }

    return buttonElement;
}

One thing to note is the use of AutomationElement.NameProperty in querying for the element. This property cannot be seen via Spy++ and I had to open the inspect the object in debugger to find it out (I used AutomationId to load an element and queried it in the debugger to find the name property).

The result of calculator can be retrieved using Result property. The setter of this property parses the character string from left to right, locates the AutomationElement for the button on the calculator corresponding to the character and then invokes it using InvokePattern’s Invoke method. This is really mimicking user typing numbers in the calculator.

public object Result
{
    get
    {
        return _resultTextBoxAutomationElement.GetCurrentPropertyValue(AutomationElement.NameProperty);
    }
    set
    {
        string stringRep = value.ToString();

        for (int index = 0; index < stringRep.Length; index++)
        {
            int leftDigit = int.Parse(stringRep[index].ToString());

            GetInvokePattern(GetDigitButton(leftDigit)).Invoke();
        }
    }
}

The Evaluate, Clear and InvokeFunction methods simply evaluates (mimicking pressing of = button), clears (mimicking pressing of C button) and invokes a function respectively:

public void Evaluate()
{
    InvokeFunction(Functions.Equals);
}

public void Clear()
{
    InvokeFunction(Functions.Clear);
}

public void InvokeFunction(string functionName)
{
    GetInvokePattern(GetFunctionButton(functionName)).Invoke();
}

FindMenu method locates the specified calculator menu and returns its ExpandCollapsePattern:

private ExpandCollapsePattern FindMenu(CalculatorMenu menu)
{
    AutomationElement menuElement = _calculatorAutomationElement.FindFirst(TreeScope.Descendants,
                                                         new PropertyCondition(AutomationElement.NameProperty, menu.ToString()));

    ExpandCollapsePattern expPattern = menuElement.GetCurrentPattern(ExpandCollapsePattern.Pattern) as
                                                                                 ExpandCollapsePattern;
    return expPattern;
}

OpenMenu and CloseMenu uses FindMenu to obtain ExpandCollapsePattern for menus and then expand and collapse menus respectively. ExecuteByMenuName looks for a menu item within expanded menu and invokes the command using the InvokePattern of the menu.

public void OpenMenu(CalculatorMenu menu)
{
    ExpandCollapsePattern expPattern = FindMenu(menu);
    expPattern.Expand();
}

public void CloseMenu(CalculatorMenu menu)
{
    ExpandCollapsePattern expPattern = FindMenu(menu);
    expPattern.Collapse();
}

public void ExecuteMenuByName(string menuName)
{
    AutomationElement menuElement = _calculatorAutomationElement.FindFirst(TreeScope.Descendants,
                                                        new PropertyCondition(AutomationElement.NameProperty, menuName));
    if (menuElement == null)
    {
        return;
    }

    InvokePattern invokePattern = menuElement.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
    if (invokePattern != null)
    {
        invokePattern.Invoke();
    }
}

Now that we have exposed functionality of calculator that we would interact with, we can proceed and model expression tree so we can evaluate expressions in the calculator. For the purpose of testing expression evaluation we need two modes of expression computation: expression evaluation through calculator UI (calculated expression) and evaluation through code (expected evaluation). If calculated expression equals expected expression we can assert that calculator computes expression in the correct manner. This evaluation option is captured via EvaluateOption enumeration:

internal enum EvaluateOption
{
    UIEvaluate,
    ActualEvaluate
}

At the end level, we need to model the operands that have sub-expressions to evaluate. Operands are modeled using IOperand interface:

internal interface IOperand
{
    int Evaluate(EvaluateOption option, Calculator calculator);
}

At the fundamental level, an operator is an operand:

internal abstract class Operator : IOperand
{       
    internal Operator(string automationName)
    {
        AutomationName = automationName;
    }

    public string AutomationName { private set; get; }

    public abstract int Evaluate(EvaluateOption option, Calculator calculator);

    protected virtual void InvokeOperator(Calculator calculator)
    {
        calculator.InvokeFunction(AutomationName);
    }
}

Automation name refers to constants within Operators class which correspond to function names in calculator (i.e.  AutomationElement.NameProperty values):

internal class Operators
{
    public const string Negate = "Negate";
    public const string Divide = "Divide";
    public const string Multiply = "Multiply";
    public const string Subtract = "Subtract";
    public const string Add = "Add";
    public const string Sqrt = "Square root";
    public const string Percentage = "Percentage";
    public const string Reciprocal = "Reciprocal";
}

A binary operator is represented using BinaryOperator abstract class:

internal abstract class BinaryOperator : Operator
{
    public BinaryOperator(string automationName)
        : base(automationName)
    {
    }

    public IOperand Left { get; set; }
       
    public IOperand Right { get; set; }

    public override int Evaluate(EvaluateOption option, Calculator calculator)
    {
        VerifyEvaluationState();
           
        int result = 0;

        switch (option)
        {
            case EvaluateOption.UIEvaluate:
                   
                calculator.Clear();
                int leftValue = Left.Evaluate(option, calculator);

                calculator.Clear();
                int rightValue = Right.Evaluate(option, calculator);

                calculator.Clear();

                calculator.Result = leftValue;

                InvokeOperator(calculator);

                calculator.Result = rightValue;

                calculator.Evaluate();

                result = int.Parse(calculator.Result.ToString());

                break;

            case EvaluateOption.ActualEvaluate:
                result = Evaluate(Left.Evaluate(option, calculator), Right.Evaluate(option, calculator));
                break;       
        }

        return result;
    }

    protected void VerifyEvaluationState()
    {
        if ((Left == null) || (Right == null))
        {
            throw new InvalidOperationException();
        }
    }

    protected abstract int Evaluate(int left, int right);
}

As can be seen if EvaluateOption.UIEvaluate is used within Evaluate function then UI automation is used to mimic the user’s input in calculator; otherwise evaluation of expression is done in code. The other Evaluate overload is implemented in derivative classes such as AddOperator, SubtractOperator, MultiplyOperator and DivideOperator. AddOperator class is as follows (rest of the operators are very similar differing only in actual computation and automation name in constructor):

internal class AddOperator : BinaryOperator
{       
    public AddOperator()
        : base(Operators.Add)
    {
    }

    protected override int Evaluate(int left, int right)
    {
        return left + right;
    }
}

NumberOperator is just a number constant in expression tree:

internal class NumberOperator : Operator
{
    public NumberOperator(int number)
        : base (null)
    {
        _number = number;
    }

    public override int Evaluate(EvaluateOption option, Calculator calculator)
    {
        return _number;
    }

    private readonly int _number;
}

ExpressionTree class creates an expression tree from a XML stream via CreateTree method:

internal static class ExpressionTree
{
    internal static IOperand CreateTree(Stream stream)
    {
        XDocument doc = XDocument.Load(stream);
        return CreateOperend(doc.Root);
    }

    private static IOperand CreateOperend(XElement operandElement)
    {
        XAttribute type = operandElement.Attribute("Type");

        IOperand operand = null;

        switch (type.Value)
        {
            case "NumberOperator":
                operand = new NumberOperator(int.Parse(operandElement.Attribute("Value").Value));
                break;

            default:
                string qualifyingName = "CalculatorTests." + type.Value;
                operand = Activator.CreateInstance(Type.GetType(qualifyingName)) as IOperand;

                List<XNode> childNodes = new List<XNode>(operandElement.Nodes());

                if (operand is BinaryOperator)
                {
                    BinaryOperator binaryOperator = operand as BinaryOperator;
                    binaryOperator.Left = CreateOperend(childNodes[0] as XElement);
                    binaryOperator.Right = CreateOperend(childNodes[1] as XElement);
                }
                else if (operand is UnaryOperator)
                {
                    UnaryOperator unaryOperator = operand as UnaryOperator;
                    unaryOperator.Operand = CreateOperend(childNodes[0] as XElement);
                }
                break;
        }

        return operand;
    }
}

CreateTree calls CreateOperend method that parses the XElement’s Type attribute to determine type of operand and depending on whether type is NumberOperator (in which case it looks for Value attribute) or otherwise (unary or binary operand in which case it looks for child Operand xml elements), it creates and returns an IOperand recursively (if needed). Finally the root operand is returned. As an example the expression (6 - 1) + (7 * 9) is represented using the xml:

<?xml version="1.0" encoding="utf-8" ?>
<Operand Type="AddOperator">
  <Operand Type="SubtractOperator">
    <Operand Type="NumberOperator" Value="6"/>
    <Operand Type="NumberOperator" Value="1"/>
  </Operand>
  <Operand Type="MultiplyOperator">
    <Operand Type="NumberOperator" Value="7"/>
    <Operand Type="NumberOperator" Value="9"/>
  </Operand>
</Operand>

Now that we have successfully created the infrastructure for interacting with the calculator and evaluating the expression tree, we can start authoring test cases:

  • Verify data entry of a random number in calculator and verify result shows up correctly in the UI

    [TestMethod]
    public void TypeRandomNumber()
    {
        using (Calculator calc = new Calculator())
        {
            int number = new Random().Next(100, 10000);
            string stringRep = number.ToString();
            calc.Result = stringRep;
            Assert.AreEqual(stringRep, calc.Result);
        }
    }
  • Verify cut and paste functionality:

    [TestMethod]
    public void VerifyCopyPaste()
    {           
        using (Calculator calc = new Calculator())
        {
            string stringRep = new Random().Next(100, 10000).ToString();               
            calc.Result = stringRep;

            calc.OpenMenu(Calculator.CalculatorMenu.Edit);
            calc.ExecuteMenuByName("Copy");

            calc.Clear();

            calc.OpenMenu(Calculator.CalculatorMenu.Edit);
            calc.ExecuteMenuByName("Paste");

            Assert.AreEqual(stringRep, calc.Result);
        }
    }

  • Verification of expression tree computation from embedded xml resource files:

    [TestMethod]
    public void VerifyExpressionTrees()
    {
        string[] files = new[]
        {
            "CalculatorTests.Resources.SimpleNumberOperator.xml",
            "CalculatorTests.Resources.SimpleAdditionOperator.xml",
            "CalculatorTests.Resources.MixedOperators.xml"
        };

        using (Calculator calc = new Calculator())
        {
            foreach (string file in files)
            {
                calc.Clear();
                IOperand expression = LoadExpressionTreeFromFile(file);
                Assert.AreEqual(expression.Evaluate(EvaluateOption.ActualEvaluate, calc), expression.Evaluate(EvaluateOption.UIEvaluate, calc));
            }
        }
    }

    private IOperand LoadExpressionTreeFromFile(string resourceFileName)
    {           
        return ExpressionTree.CreateTree(this.GetType().Assembly.GetManifestResourceStream(resourceFileName));
    }

You may run the tests using Visual Studio test manager and will see calculator instances popping up and controls being manipulated as per the test cases followed by termination of calculator process (remember the IDisposable implementation in Calculator class that does the teardown).

So that’s it, you have just seen an automation client in action! Stay tuned for my next blog where I will demonstrate how to implement automation support during the development of custom controls.

You may also want to look at project White on codeplex which is based on UI automation framework and aims to simplify UI automation programming model.

Monday, December 27, 2010

Create custom windows in WPF with ease

One of the features I wanted to add to Synergy toolkit was the ability to quickly create custom theme windows with all the features of a standard windows. In this article I am demonstrating how to create a custom window theme visually using declarative XAML and apply it to windows in your applications.

You can download Synergy SDK with full source code here.
You may also want to see my window docking solution in Synergy here.
I will be posting updates on Synergy SDK on my twitter account: MixModes

The sample application Synergy uses main window as the custom window whose theme is defined within Windows.xaml resource dictionary within MixModes.Synergy.Themes project.

Declarative is the key

As we all know XAML is declarative and simple and so there is no reason why traditional approach of writing code for windows and controls should apply. One must be able to simply create a visual and stick it in a control template to get things working. That was exactly my motivation when I started out developing look-less window functionality in Synergy.

Declare a template

The first thing you may want to do in creating a custom window is to actually create a visual template. The easiest way to create this template is to create a user control in Microsoft Blend and then define extension points in XAML that look-less control will liven up once the template is applied. Once the visual is ready all that needs to be done is a style creation for CustomWindow where the template can be pasted and then the temporary user control can be discarded.

Following extension points are supported for current implementation:

  • PART_TITLEBAR (UIElement) - For displaying window title, dragging and maximize / restore operations
  • PART_MINIMIZE (Button) – Window minimize button
  • PART_MAXIMIZE_RESTORE (Button) – Maximize restore button
  • PART_CLOSE (Button) – Close button
  • PART_LEFT_BORDER (UIElement) – Left resizable border
  • PART_RIGHT_BORDER (UIElement) – Right resizable border
  • PART_TOP_BORDER (UIElement) – Top resizable border
  • PART_BOTTOM_BORDER (UIElement) – Bottom resizable border

One more thing to note is that while defining the window template, you must declare the ContentPresenter (which ultimately contains window content) within AdornerDecorator tag (which is the adorner layer for the window) as this is WPF requirement.

Here is the template I have created within Windows.xaml resource dictionary within MixModes.Synergy.Themes project:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                                             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="MainWindow"
           TargetType="{x:Type Window}">
        <Setter Property="Foreground"
                Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Window}">
                    <Grid>
                        <Border x:Name="MainBorder"
                                BorderBrush="{DynamicResource MainWindowBorderBrush}"
                                BorderThickness="1"
                                CornerRadius="2"
                                Background="{DynamicResource MainWindowBackgroundBrush}">
                            <DockPanel LastChildFill="True">
                                <Rectangle x:Name="PART_LEFT_BORDER"
                                           Width="2"
                                           Cursor="SizeWE">
                                    <Rectangle.Fill>
                                        <SolidColorBrush Color="Transparent" />
                                    </Rectangle.Fill>
                                </Rectangle>
                                <Rectangle x:Name="PART_RIGHT_BORDER"
                                           Cursor="SizeWE"
                                           Width="2"
                                           DockPanel.Dock="Right">
                                    <Rectangle.Fill>
                                        <SolidColorBrush Color="Transparent" />
                                    </Rectangle.Fill>
                                </Rectangle>
                                <Rectangle x:Name="PART_TOP_BORDER"
                                           Cursor="SizeNS"
                                           DockPanel.Dock="Top"
                                           Height="2">
                                    <Rectangle.Fill>
                                        <SolidColorBrush Color="Transparent" />
                                    </Rectangle.Fill>
                                </Rectangle>
                                <Rectangle x:Name="PART_BOTTOM_BORDER"
                                           Cursor="SizeNS"
                                           Height="2"
                                           DockPanel.Dock="Bottom">
                                    <Rectangle.Fill>
                                        <SolidColorBrush Color="Transparent" />
                                    </Rectangle.Fill>
                                </Rectangle>
                                <Border x:Name="PART_TITLEBAR"
                                        Margin="2,0,2,2"
                                        Height="40"
                                        DockPanel.Dock="Top"
                                        CornerRadius="2"
                                        Background="Transparent">
                                    <DockPanel LastChildFill="False">
                                        <TextBlock Margin="8,0,0,4"
                                                   VerticalAlignment="Center"
                                                   FontStretch="UltraExpanded"
                                                   Foreground="Black"
                                                   TextTrimming="CharacterEllipsis"
                                                   TextWrapping="NoWrap"
                                                   Text="{TemplateBinding Title}"
                                                   FontSize="16" />
                                        <Button x:Name="PART_CLOSE"
                                                DockPanel.Dock="Right"
                                                Style="{DynamicResource FlatButton}"
                                                VerticalAlignment="Center"
                                                Margin="0,0,4,0">
                                            <Image Source="/MixModes.Synergy.Resources;component/Resources/Close.png"
                                                   Stretch="None"
                                                   Margin="4" />
                                        </Button>
                                        <Button x:Name="PART_MAXIMIZE_RESTORE"
                                                DockPanel.Dock="Right"
                                                HorizontalAlignment="Center"
                                                VerticalAlignment="Center"
                                                Style="{DynamicResource FlatButton}">
                                            <Image x:Name="MaximizeRestoreImage"
                                                   Source="/MixModes.Synergy.Resources;component/Resources/Restore.png"
                                                   Stretch="None"
                                                   Margin="4" />
                                        </Button>
                                        <Button x:Name="PART_MINIMIZE"
                                                HorizontalAlignment="Center"
                                                Style="{DynamicResource FlatButton}"
                                                VerticalAlignment="Center"
                                                DockPanel.Dock="Right">
                                            <Image Margin="4"
                                                   Source="/MixModes.Synergy.Resources;component/Resources/Minimize.png"
                                                   Stretch="None" />
                                        </Button>
                                    </DockPanel>
                                </Border>

                                <!-- Title bar separator-->
                                <Border Height="1"
                                        DockPanel.Dock="Top"
                                        Background="{DynamicResource MainWindowTitleBarSeparator}" />

                                <!-- Actual Window Content -->
                                <AdornerDecorator DockPanel.Dock="Bottom">
                                    <ContentPresenter />
                                </AdornerDecorator>
                            </DockPanel>
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>                       
                        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Maximized}"
                                     Value="False">
                            <Setter TargetName="MaximizeRestoreImage"
                                    Property="Source"
                                    Value="/MixModes.Synergy.Resources;component/Resources/Maximize.png" />
                        </DataTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

This is a pretty simple theme which creates a rounded rectangle window with 2 pixel wide resizers and custom window minimize, maximize and restore buttons. It also contains a template trigger that changes the image of maximize restore button if window is not maximized.

The window created using this theme looks like the following:

image

Inherit from CustomWindow class

The final step is to inherit from CustomWindow class (which in turn inherits from Window class) instead of directly inheriting from Window class and refer to the style created in the previous step. This is again very simple:

  • Import visual framework namespace:
    xmlns:visualFx="http://mixmodes.com/visualFx"
  • Inherit from CustomWindow class:
    use “visualFx:CustomWindow” as your window tag in XAML
  • Refer to the style created in previous step in your visualFx:CustomWindow tag:
    Style="{DynamicResource MainWindow}"

That’s all you have to do to get your custom window working !

How does it work?

If you crack open the CustomWindow class you will see that bulk of the work happens in the AttachToVisualTree method which is called from OnApplyTemplate (which in turn is called anytime template is applied to our custom window).

AttachToVisualTree in turn calls AttachCloseButton, AttachMaximizeButton, AttachMaximizeRestoreButton, AttachTitleBar and AttachBorders methods, each of which queries for visual parts (the PART_… named parts we defined in the template) and attaches functionality via events.

So that’s it ! Creating custom windows using Synergy is really that simple !