Tuesday, January 27, 2009

Guidance on Ahead of Time Compilation for Mono 2.2?

Does anyone have recommendations on using ahead of time compilation for the system libraries under Mono 2.2? The Mono website has this article with some (outdated?) information about how to carry it out. I tried following the instructions with the following exceptions:
  • I found multiple mscorlib.dll assemblies (at /usr/lib/mono/1.0, 2.0, 2.1) and tried AOT-compiling all of them. Only the 1.0 and 2.0 assemblies succeeded. The 2.1 assembly kept referring to the 2.0 assembly and never produced the .so file for itself.
  • Several assemblies (System.Xml.dll for one) in the GAC failed to precompile. The AOT compilation process for that one complained that it could not load the System assembly.
When I tried executing Mono executables (themselves also AOT-compiled and working prior to my pre-compilation of the system assemblies), they universally failed with Mono framework errors.

Has anyone successfully AOT-compiled the system assemblies under Mono 2.2? Is this even a good idea, assuming there's a way to make it work?

Monday, January 19, 2009

Yet another WPF HyperlinkButton control

I wanted a general purpose implementation of the Silverlight HyperlinkButton for WPF that supported binding things like the font, font weight, etc. so I quickly rolled this puppy. It has its own Click event so clients can subscribe appropriately. I am sure there are some enhancements lurking, but it seems to do the job:

XAML:

<UserControl x:Class="Controls.HyperlinkButton"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="root"
    >
    <TextBlock x:Name="hyperlinkContentText"
        Text="{Binding HyperlinkContent, ElementName=root}"
        FontSize="{Binding FontSize, ElementName=root, Path=FontSize}"
        FontFamily="{Binding FontFamily, ElementName=root, Path=FontFamily}"
        FontStretch="{Binding FontStretch, ElementName=root, Path=FontStretch}"
        FontStyle="{Binding FontStyle, ElementName=root, Path=FontStyle}"
        FontWeight="{Binding FontWeight, ElementName=root, Path=FontWeight}"
        Foreground="{Binding Foreground, ElementName=root, Path=Foreground}"
        Background="{Binding Background, ElementName=root, Path=Background}"
        Opacity="{Binding Opacity, ElementName=root, Path=Opacity}"
        OpacityMask="{Binding OpacityMask, ElementName=root, Path=OpacityMask}"
        MouseEnter="hyperlinkContentText_MouseEnter"
        MouseLeave="hyperlinkContentText_MouseLeave"
        MouseLeftButtonDown="hyperlinkContentText_MouseLeftButtonDown" />
</UserControl>

Code-behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Controls
{
    /// <summary>
    /// Interaction logic for HyperlinkButton.xaml
    /// </summary>
    public partial class HyperlinkButton : UserControl
    {
        #region dependency properties
        /// <summary>
        /// Dependency property for hyperlink text content.
        /// </summary>
        public static readonly DependencyProperty HyperlinkContentProperty;
        #endregion

        #region routed events
        /// <summary>
        /// Routed event for handling the "button" click.
        /// </summary>
        public static readonly RoutedEvent ClickEvent;
        #endregion

        #region ctor
        #region static
        /// <summary>
        /// Initializes the <see cref="HyperlinkButton"/> class.
        /// </summary>
        static HyperlinkButton()
        {
            FrameworkPropertyMetadata fpm = new FrameworkPropertyMetadata(string.Empty);
            HyperlinkContentProperty = DependencyProperty.Register(
                "HyperlinkContent",
                typeof(string),
                typeof(FrameworkElement),
                fpm);

            ClickEvent = EventManager.RegisterRoutedEvent(
                "Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(HyperlinkButton));
        }
        #endregion

        #region instance
        /// <summary>
        /// Initializes a new instance of the <see cref="HyperlinkButton"/> class.
        /// </summary>
        public HyperlinkButton()
        {
            InitializeComponent();
        }
        #endregion
        #endregion

        #region properties
        /// <summary>
        /// Gets or sets the content of the hyperlink.
        /// </summary>
        /// <value>The content of the hyperlink.</value>
        public string HyperlinkContent
        {
            get { return (string)GetValue(HyperlinkContentProperty); }
            set { SetValue(HyperlinkContentProperty, value); }
        }

        /// <summary>
        /// Occurs when [click].
        /// </summary>
        public event RoutedEventHandler Click
        {
            add
            {
                AddHandler(ClickEvent, value);
            }
            remove
            {
                RemoveHandler(ClickEvent, value);
            }
        }
        #endregion

        #region event handlers
        /// <summary>
        /// Handles the MouseEnter event of the hyperlinkContentText control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseEventArgs"/> instance containing the event data.</param>
        private void hyperlinkContentText_MouseEnter(object sender, MouseEventArgs e)
        {
            hyperlinkContentText.TextDecorations = TextDecorations.Underline;
            hyperlinkContentText.Cursor = Cursors.Hand;
        }

        /// <summary>
        /// Handles the MouseLeave event of the hyperlinkContentText control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseEventArgs"/> instance containing the event data.</param>
        private void hyperlinkContentText_MouseLeave(object sender, MouseEventArgs e)
        {
            hyperlinkContentText.TextDecorations = null;
            hyperlinkContentText.Cursor = Cursors.Arrow;
        }

        /// <summary>
        /// Handles the MouseLeftButtonDown event of the hyperlinkContentText control. Maps it to the click
        /// event of this control and suppresses it after raising Click.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
        private void hyperlinkContentText_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
            RaiseEvent(new RoutedEventArgs(ClickEvent, this));
        }
        #endregion
    }
}