Saturday, January 17, 2009

Fujitsu T5010 Drivers for Windows 7 64-bit

While Fujitsu does not officially support Windows Vista or Windows 7 64-bit, there are already drivers available for most devices. Here are what I have found. Agere Systems HDA Modem - 2.1.87 http://www.versiontracker.com/dyn/moreinfo/win/163452 Wacom Penabled Tablet http://www.wacom.com/tabletpc/driver.cfm Intel GM45 Chipset INF Update Utility - Zip Format http://downloadcenter.intel.com/filter_results.aspx?strTypes=all&ProductID=816&OSFullName=Windows+Vista*+64&lang=eng&strOSs=150&submit=Go! O2Micro SD/Memory Stick Card Reader http://www.download.com/O2Micro-CardReader-xp-vista-NB-zip/3000-2122_4-185343.html ACPI Device Driver (FUJ02B1) ACPI Device Driver (FUJ02E3) Fujitsu Tablet Button Driver Fujitsu Tablet Button Utility O2Micro SmartCard Device Driver http://www.pc-ap.fujitsu.com/support/drv_lb_vis64_t4220.html Fingerprint Reader (For Windows 7 only) http://www.authentec.com/win7beta64.cfm Audio and Graphics - Intel® Graphics Media Accelerator Driver for Windows Vista* 64 (zip) http://downloadcenter.intel.com/filter_results.aspx?strTypes=all&ProductID=2991&OSFullName=Windows+Vista*+Ultimate%2C+64-bit+version&lang=eng&strOSs=162&submit=Go! http://www.download.com/Realtek-High-Definition-Audio-Codec-Windows-Vista-/3000-2120_4-10788600.html?tag=mncol Touchpad http://www.synaptics.com/support/drivers Have not found a driver that supports the Scroll Sensor beside the screen. Here's what device manager shows

Tuesday, January 06, 2009

How to recover from an accidental deletion of linux boot partition (Part 3 of 3)

Again, life didn't go so smoothly. Before resorting to using VirtualBox to recreate the files in the boot partition, I chose the Install or Upgrade option of the Fedora DVD. I tried to do an upgrade on the existing partition, namely /dev/VolGroup00/LogVol00. The installation failed with an exception thrown. Then I resorted to VirtualBox and doing everything in Part 2. Upon rebooting, all went well, GUI grub loaded, Fedora boot screen came out, and then comes the login screen. Waited. Nothing happened. Some files must have been corrupted by the failed upgrade.

Recover process

Boot into Fedora DVD. Choose the Install or Upgrade option. Upgrade the existing partition. The installation should proceed smoothly now. Fedora recovered!

How to recover from an accidental deletion of linux boot partition (Part 2 of 3)

Continuing from the previous post. Everything would have been up and running again if I had did exactly as said in the previous post. However, I did an extra step. As suggested in forums, to create a partition, I would first fdisk and then mkfs.ext3. So I went to type this instead. sda7 is the newly created partition. #fdisk /dev/sda n p 1 <enter> <enter> w #mkfs.ext3 /dev/sda7 #reboot Again the grub screen, with the kernel totally gone.

Recovery Process

Boot into Vista, install VirtualBox (VirtualPC didn't work. No USB support). All the steps below are done in VirtualBox. Create new virtual machine. Install Fedora 10. (Default installation) Boot into Fedora. swapoff -a, delete the swap partition and edit fstab. (this is to create a configuration that matches my Fedora installation on my hard disk before I deleted my boot partition) Insert thumb drive and capture it. Open Terminal. Switch to root (su). Copy everything in /boot into my thumb drive, which is mounted on /mnt/TOSHIBA Shut down Fedora. Exit out of VirtualBox. Shut down Vista. Boot into Fedora DVD. Go into Rescue Installed System. Select English, US keyboard, no network. To find which device is the thumb drive, type #blkid My system showed /dev/sdb1: LABEL="TOSHIBA" UUID=... Also, note down the UUID of the root partition, we will need it later. /dev/dm-0: UUID="<note down this long string>" TYPE="ext3" Mount the thumb drive as follows #mkdir /mnt/thumb #mount /dev/sdb1 /mnt/thumb Mount the boot partition #mkdir /mnt/boot #mount /dev/sda7 /mnt/boot Copy everything from the thumb drive to the boot partition. Next is to edit grub.conf #nano /mnt/boot/grub/grub.conf Change the timeout=0 to timeout=5 After hiddenmenu add the following to create the Windows Vista boot option.
title Windows Vista
    rootnoverify (hd0,1)
    chainloader +1
For the line beginning with kernel /vmlinuz, replace the UUID in the root=UUID=<replace this what you note down just now> To save, Ctrl+O To exit, Ctrl+X #reboot Fedora recovered!

How to recover from an accidental deletion of linux boot partition (Part 1 of 3)

Being new to Linux, I made a big mistake in deleting the boot partition. The story goes like this. A hard disk supports at most 4 partitions. I had Windows Vista and Fedora 10 installed. My system has 2 partitions taken up by the system recovery image. Windows Vista's Disk Management reports the partitions as follows 6 partitions? Hmm, I thought it could have been that the recovery partitions were special and does not take up entries in the partition table. Then I wanted to free up one partition to make (partition table) space for Windows 7 Beta 1. So Linux swap partition shall go. As I had tried out Fedora 2 long time ago, I thought the 3rd partition was Linux swap and 4th the Linux root. Booted into Linux, swapoff and edited the /etc/fstab file to exclude the swap partition. Booted back to Vista, deleted the 3rd partition. Boom! The truth revealed... I have in fact only 4 partitions! The 2 Linux partitions were on the extended partition. Rebooted my computer. All is not well... At start-up To boot into Vista, I had to type rootnoverify (hd0,1) chainloader +1 boot After looking through a number of websites, it finally dawned on me that the default Fedora partitioning had changed. The 3rd partition is a boot partition and the 4th is an LVM partition, which contains both swap and root. (both are totally new to me) No boot partition means no Fedora kernel, and that means my Fedora will never boot! Oh no!

Recovery process

Boot from the Fedora DVD. Go into Rescue Installed System. Select English, US keyboard, no network. Next step is to re-create the boot partition. #fdisk /dev/sda n p 1 <enter> <enter> w #reboot Fedora recovered!

Saturday, October 25, 2008

Placeholder text using Adorner, improved

Previously, my adorner only supports TextBox, RichTextBox and PasswordBox. I found it limiting, as there are so many controls out there that supports editing text. One such case is the ComboBox with the IsEditable property set to true. After trying to add a new code brunch to support the case of ComboBox, I bumped into a wall. The IsFocused property of ComboBox is not reporting the right thing! It reports not focused even with my cursor blinking inside the ComboBox. On examining the visual tree, I found the culprit - the TextBox in the ComboBox is having the focus, not the ComboBox itself. Solution? Hunt for this TextBox! So here comes an updated adorner that searches the visual tree for a TextBox if the attached property is placed on a control other than a TextBox, RichTextBox or PasswordBox. Turned out to be more powerful than originally planned =). One more feature improvement is to have the option not to hide the placeholder text even if the control have the focus (set HideOnFocus to false). This allows you to focus on the control when the application start up and still have the prompt there to tell your user what to do. Miles of code coming your way, watch out!

//-----------------------------------------------------------------------

// <copyright file="Placeholder.cs" company="Jeow Li Huan">

// Copyright (c) Jeow Li Huan. All rights reserved.

// </copyright>

//-----------------------------------------------------------------------

 

using System;

using System.Collections.Generic;

using System.Globalization;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Controls.Primitives;

using System.Windows.Documents;

using System.Windows.Media;

 

namespace TetonWhitewaterKayak.WinUI

{

    /// <summary>

    ///   Represents an adorner that adds placeholder text to a <see cref="T:System.Windows.Controls.TextBox"/>,

    ///   <see cref="T:System.Windows.Controls.RichTextBox"/> or <see cref="T:System.Windows.Controls.PasswordBox"/>.

    /// </summary>

    public class Placeholder : Adorner

    {

        #region Dependency Property

        /// <summary>

        ///   Identifies the <see cref="T:Huan.Windows.Documents.Placeholder" />.Text attached property.

        /// </summary>

        public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached(

            "Text",

            typeof(string),

            typeof(Placeholder),

            new FrameworkPropertyMetadata(string.Empty, OnTextChanged));

 

        /// <summary>

        ///   Identifies the <see cref="T:Huan.Windows.Documents.Placeholder" />.HideOnFocus attached property.

        /// </summary>

        public static readonly DependencyProperty HideOnFocusProperty = DependencyProperty.RegisterAttached(

            "HideOnFocus",

            typeof(bool),

            typeof(Placeholder),

            new FrameworkPropertyMetadata(true, OnHideOnFocusChanged));

        #endregion

 

        /// <summary>

        ///   <see langword="true"/> when the placeholder text is visible, <see langword="false" /> otherwise.

        ///   Used to avoid calling <see cref="M:System.Windows.UIElement.InvalidateVisual"/> unnecessarily.

        /// </summary>

        private bool isPlaceholderVisible;

 

        #region Constructors

        /// <summary>

        ///   Initializes static members of the <see cref="T:Huan.Windows.Documents.Placeholder"/> class.

        /// </summary>

        static Placeholder()

        {

            IsHitTestVisibleProperty.OverrideMetadata(typeof(Placeholder), new FrameworkPropertyMetadata(false));

            ClipToBoundsProperty.OverrideMetadata(typeof(Placeholder), new FrameworkPropertyMetadata(true));

        }

 

        /// <summary>

        ///   Initializes a new instance of the <see cref="T:Huan.Windows.Documents.Placeholder"/> class.

        /// </summary>

        /// <param name="adornedElement">

        ///   The element to bind the adorner to.

        /// </param>

        /// <exception cref="T:System.ArgumentNullException">

        ///   Raised when adornedElement is null.

        /// </exception>

        public Placeholder(PasswordBox adornedElement)

            : this((Control)adornedElement)

        {

            if (!(adornedElement.IsFocused && (bool)adornedElement.GetValue(HideOnFocusProperty)))

                adornedElement.PasswordChanged += this.AdornedElement_ContentChanged;

        }

 

        /// <summary>

        ///   Initializes a new instance of the <see cref="T:Huan.Windows.Documents.Placeholder"/> class.

        /// </summary>

        /// <param name="adornedElement">

        ///   The element to bind the adorner to.

        /// </param>

        /// <exception cref="T:System.ArgumentNullException">

        ///   Raised when adornedElement is null.

        /// </exception>

        public Placeholder(TextBoxBase adornedElement)

            : this((Control)adornedElement)

        {

            if (!(adornedElement.IsFocused && (bool)adornedElement.GetValue(HideOnFocusProperty)))

                adornedElement.TextChanged += this.AdornedElement_ContentChanged;

        }

 

        /// <summary>

        ///   Initializes a new instance of the <see cref="T:Huan.Windows.Documents.Placeholder"/> class.

        /// </summary>

        /// <param name="adornedElement">

        ///   The element to bind the adorner to.

        /// </param>

        /// <exception cref="T:System.ArgumentNullException">

        ///   Raised when adornedElement is null.

        /// </exception>

        protected Placeholder(Control adornedElement)

            : base(adornedElement)

        {

            if ((bool)adornedElement.GetValue(HideOnFocusProperty))

            {

                adornedElement.GotFocus += this.AdornedElement_GotFocus;

                adornedElement.LostFocus += this.AdornedElement_LostFocus;

            }

        }

        #endregion

 

        #region Attached Property Getters and Setters

        /// <summary>

        ///   Gets the value of the <see cref="T:Huan.Windows.Documents.Placeholder" />.Text attached property for a specified element.

        /// </summary>

        /// <param name="adornedElement">

        ///   The element from which the property value is read.

        /// </param>

        /// <returns>

        ///   The placeholder text property value for the element.

        /// </returns>

        /// <exception cref="T:ArgumentNullException">

        ///   Raised when adornedElement is null.

        /// </exception>

        public static string GetText(Control adornedElement)

        {

            if (adornedElement == null)

                throw new ArgumentNullException("adornedElement");

            return (string)adornedElement.GetValue(TextProperty);

        }

 

        /// <summary>

        ///   Sets the value of the <see cref="T:Huan.Windows.Documents.Placeholder" />.Text attached property to a specified element.

        /// </summary>

        /// <param name="adornedElement">

        ///   The element to which the attached property is written.

        /// </param>

        /// <param name="placeholderText">

        ///   The needed placeholder text value.

        /// </param>

        /// <exception cref="T:ArgumentNullException">

        ///   Raised when adornedElement is null.

        /// </exception>

        /// <exception cref="T:InvalidOperationException">

        ///   Raised when adornedElement is not a <see cref="T:System.Windows.Controls.TextBox"/>,

        ///   <see cref="T:System.Windows.Controls.RichTextBox"/> or <see cref="T:System.Windows.Controls.PasswordBox"/>.

        /// </exception>

        public static void SetText(Control adornedElement, string placeholderText)

        {

            if (adornedElement == null)

                throw new ArgumentNullException("adornedElement");

            adornedElement.SetValue(TextProperty, placeholderText);

        }

 

        /// <summary>

        ///   Gets the value of the <see cref="T:Huan.Windows.Documents.Placeholder" />.HideOnFocus attached property for a specified element.

        /// </summary>

        /// <param name="adornedElement">

        ///   The element from which the property value is read.

        /// </param>

        /// <returns>

        ///   A value indicating whether the control will be hidden when the element is in focus.

        /// </returns>

        /// <exception cref="T:ArgumentNullException">

        ///   Raised when adornedElement is null.

        /// </exception>

        public static bool GetHideOnFocus(Control adornedElement)

        {

            if (adornedElement == null)

                throw new ArgumentNullException("adornedElement");

            return (bool)adornedElement.GetValue(HideOnFocusProperty);

        }

 

        /// <summary>

        ///   Sets the value of the <see cref="T:Huan.Windows.Documents.Placeholder" />.HideOnFocus attached property to a specified element.

        /// </summary>

        /// <param name="adornedElement">

        ///   The element to which the attached property is written.

        /// </param>

        /// <param name="hideOnFocus">

        ///   A value indicating whether to hide the placeholder text when the element is in focus.

        /// </param>

        /// <exception cref="T:ArgumentNullException">

        ///   Raised when adornedElement is null.

        /// </exception>

        /// <exception cref="T:InvalidOperationException">

        ///   Raised when adornedElement is not a <see cref="T:System.Windows.Controls.TextBox"/>,

        ///   <see cref="T:System.Windows.Controls.RichTextBox"/> or <see cref="T:System.Windows.Controls.PasswordBox"/>.

        /// </exception>

        public static void SetHideOnFocus(Control adornedElement, bool hideOnFocus)

        {

            if (adornedElement == null)

                throw new ArgumentNullException("adornedElement");

            adornedElement.SetValue(HideOnFocusProperty, hideOnFocus);

        }

        #endregion

 

        /// <summary>

        ///   Draws the content of a <see cref="T:System.Windows.Media.DrawingContext" /> object during the render pass of a <see cref="T:Huan.Windows.Documents.Placeholder"/> element.

        /// </summary>

        /// <param name="drawingContext">

        ///   The <see cref="T:System.Windows.Media.DrawingContext" /> object to draw. This context is provided to the layout system.

        /// </param>

        protected override void OnRender(DrawingContext drawingContext)

        {

            Control adornedElement = this.AdornedElement as Control;

            string placeholderText;

            bool hideOnFocus = (bool)adornedElement.GetValue(HideOnFocusProperty);

 

            if (adornedElement == null ||

                (adornedElement.IsFocused && hideOnFocus) ||

                !this.IsElementEmpty() ||

                string.IsNullOrEmpty(placeholderText = (string)adornedElement.GetValue(TextProperty)))

 

                this.isPlaceholderVisible = false;

            else

            {

                this.isPlaceholderVisible = true;

                Size size = adornedElement.RenderSize;

                double maxHeight = size.Height - adornedElement.BorderThickness.Top - adornedElement.BorderThickness.Bottom - adornedElement.Padding.Top - adornedElement.Padding.Bottom;

                double maxWidth = size.Width - adornedElement.BorderThickness.Left - adornedElement.BorderThickness.Right - adornedElement.Padding.Left - adornedElement.Padding.Right - 4.0;

                if (maxHeight <= 0 || maxWidth <= 0)

                    return;

 

                TextAlignment computedTextAlignment = this.ComputedTextAlignment();

 

                // Foreground brush does not need to be dynamic. OnRender called when SystemColors changes.

                Brush foreground = SystemColors.GrayTextBrush.Clone();

 

                foreground.Opacity = adornedElement.Foreground.Opacity;

                Typeface typeface = new Typeface(adornedElement.FontFamily, FontStyles.Italic, adornedElement.FontWeight, adornedElement.FontStretch);

                FormattedText formattedText = new FormattedText(

                    placeholderText,

                    CultureInfo.CurrentCulture,

                    adornedElement.FlowDirection,

                    typeface,

                    adornedElement.FontSize,

                    foreground);

                formattedText.TextAlignment = computedTextAlignment;

                formattedText.MaxTextHeight = maxHeight;

                formattedText.MaxTextWidth = maxWidth;

 

                double left;

                double top = 0.0;

                if (adornedElement.FlowDirection == FlowDirection.RightToLeft)

                    left = adornedElement.BorderThickness.Right + adornedElement.Padding.Right + 2.0;

                else

                    left = adornedElement.BorderThickness.Left + adornedElement.Padding.Left + 2.0;

                switch (adornedElement.VerticalContentAlignment)

                {

                    case VerticalAlignment.Top:

                    case VerticalAlignment.Stretch:

                        top = adornedElement.BorderThickness.Top + adornedElement.Padding.Top;

                        break;

                    case VerticalAlignment.Bottom:

                        top = size.Height - adornedElement.BorderThickness.Bottom - adornedElement.Padding.Bottom - formattedText.Height;

                        break;

                    case VerticalAlignment.Center:

                        top = (size.Height + adornedElement.BorderThickness.Top - adornedElement.BorderThickness.Bottom + adornedElement.Padding.Top - adornedElement.Padding.Bottom - formattedText.Height) / 2.0;

                        break;

                }

 

                if (adornedElement.FlowDirection == FlowDirection.RightToLeft)

                {

                    // Somehow everything got drawn reflected. Add a transform to correct.

                    drawingContext.PushTransform(new ScaleTransform(-1.0, 1.0, RenderSize.Width / 2.0, 0.0));

                    drawingContext.DrawText(formattedText, new Point(left, top));

                    drawingContext.Pop();

                }

                else

                    drawingContext.DrawText(formattedText, new Point(left, top));

            }

        }

 

        /// <summary>

        ///   Adds a <see cref="T:Huan.Windows.Documents.Placeholder"/> to the adorner layer.

        /// </summary>

        /// <param name="adornedElement">

        ///   The adorned element.

        /// </param>

        private static void AddAdorner(Control adornedElement)

        {

            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(adornedElement);

            if (adornerLayer == null)

                return;

            Adorner[] adorners = adornerLayer.GetAdorners(adornedElement);

            if (adorners != null)

                foreach (Adorner adorner in adorners)

                    if (adorner is Placeholder)

                    {

                        adorner.InvalidateVisual();

                        return;

                    }

 

            TextBox textBox = adornedElement as TextBox;

            if (textBox != null)

            {

                adornerLayer.Add(new Placeholder(textBox));

                return;

            }

 

            RichTextBox richTextBox = adornedElement as RichTextBox;

            if (richTextBox != null)

            {

                adornerLayer.Add(new Placeholder(richTextBox));

                return;

            }

 

            PasswordBox passwordBox = adornedElement as PasswordBox;

            if (passwordBox != null)

            {

                adornerLayer.Add(new Placeholder(passwordBox));

                return;

            }

 

            // TextBox is hidden in template. Search for it.

            TextBox templateTextBox = null;

            templateTextBox = FindTextBox(adornedElement);

            if (templateTextBox != null)

                Placeholder.SetText(templateTextBox, (string)Placeholder.GetText(adornedElement));

        }

 

        /// <summary>

        ///   Finds a <see cref="T:System.Windows.Controls.TextBox"/> in the visual tree of the adorned element using a breadth first search.

        /// </summary>

        /// <param name="adornedElement">The adorned element which visual tree is searched for a <see cref="T:System.Windows.Controls.TextBox"/>.</param>

        /// <returns>The <see cref="T:System.Windows.Controls.TextBox"/> if one is found, <see langword="null"/> if none exists.</returns>

        private static TextBox FindTextBox(Control adornedElement)

        {

            TextBox templateTextBox = null;

            Queue<DependencyObject> queue = new Queue<DependencyObject>();

            queue.Enqueue(adornedElement);

            while (queue.Count > 0)

            {

                DependencyObject element = queue.Dequeue();

                templateTextBox = element as TextBox;

                if (templateTextBox != null)

                    break;

 

                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); ++i)

                    queue.Enqueue(VisualTreeHelper.GetChild(element, i));

            }

 

            return templateTextBox;

        }

 

        /// <summary>

        ///   Event handler for AdornedElement.Loaded.

        /// </summary>

        /// <param name="sender">

        ///   The AdornedElement where the event handler is attached.

        /// </param>

        /// <param name="e">

        ///   Provides data about the event.

        /// </param>

        private static void AdornedElement_Loaded(object sender, RoutedEventArgs e)

        {

            Control adornedElement = (Control)sender;

            adornedElement.Loaded -= AdornedElement_Loaded;

            AddAdorner(adornedElement);

        }

 

        /// <summary>

        ///   Invoked whenever <see cref="T:Huan.Windows.Documents.Placeholder" />.Text attached property is changed.

        /// </summary>

        /// <param name="sender">

        ///   The object where the event handler is attached.

        /// </param>

        /// <param name="e">

        ///   Provides data about the event.

        /// </param>

        private static void OnTextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)

        {

            if (((string)e.OldValue).Equals((string)e.NewValue, StringComparison.Ordinal))

                return;

 

            Control adornedElement = sender as Control;

            if (adornedElement == null)

                return;

 

            if (adornedElement.IsLoaded)

                AddAdorner(adornedElement);

            else

                adornedElement.Loaded += AdornedElement_Loaded;

        }

 

        /// <summary>

        ///   Invoked whenever <see cref="T:Huan.Windows.Documents.Placeholder" />.HideOnFocus attached property is changed.

        /// </summary>

        /// <param name="sender">

        ///   The object where the event handler is attached.

        /// </param>

        /// <param name="e">

        ///   Provides data about the event.

        /// </param>

        private static void OnHideOnFocusChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)

        {

            bool hideOnFocus = (bool)e.NewValue;

            if ((bool)e.OldValue == hideOnFocus)

                return;

 

            Control adornedElement = sender as Control;

 

            if (!(adornedElement is TextBox || adornedElement is PasswordBox || adornedElement is RichTextBox))

            {

                if (!adornedElement.IsLoaded)

                    adornedElement.Loaded += ChangeHideOnFocus;

                else

                {

                    TextBox templateTextBox = FindTextBox(adornedElement);

                    if (templateTextBox != null)

                        Placeholder.SetHideOnFocus(templateTextBox, (bool)e.NewValue);

                }

 

                return;

            }

 

            Placeholder placeholder = null;

            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(adornedElement);

            if (adornerLayer == null)

                return;

 

            Adorner[] adorners = adornerLayer.GetAdorners(adornedElement);

            if (adorners != null)

                foreach (Adorner adorner in adorners)

                {

                    placeholder = adorner as Placeholder;

                    if (placeholder != null)

                        break;

                }

 

            if (placeholder == null)

                return;

 

            if (adornedElement.IsLoaded)

            {

                if (hideOnFocus)

                {

                    adornedElement.GotFocus += placeholder.AdornedElement_GotFocus;

                    adornedElement.LostFocus += placeholder.AdornedElement_LostFocus;

                    if (adornedElement.IsFocused && placeholder.isPlaceholderVisible)

                        placeholder.InvalidateVisual();

                }

                else

                {

                    adornedElement.GotFocus -= placeholder.AdornedElement_GotFocus;

                    adornedElement.LostFocus -= placeholder.AdornedElement_LostFocus;

                    placeholder.AdornedElement_LostFocus(adornedElement, new RoutedEventArgs(UIElement.LostFocusEvent, placeholder));

                }

            }

            else

                adornedElement.Loaded += AdornedElement_Loaded;

        }

 

        /// <summary>

        ///   Changes the HideOnFocus property of the text box in the visual tree of the sender.

        /// </summary>

        /// <param name="sender">The object where the event handler is attached.</param>

        /// <param name="e">Provides data about the event.</param>

        private static void ChangeHideOnFocus(object sender, RoutedEventArgs e)

        {

            Control adornedElement = sender as Control;

            if (adornedElement == null)

                return;

 

            TextBox templateTextBox = FindTextBox(adornedElement);

            if (templateTextBox != null)

                Placeholder.SetHideOnFocus(templateTextBox, Placeholder.GetHideOnFocus(adornedElement));

        }

 

        #region Event Handlers

        /// <summary>

        ///   Event handler for AdornedElement.GotFocus.

        /// </summary>

        /// <param name="sender">

        ///   The AdornedElement where the event handler is attached.

        /// </param>

        /// <param name="e">

        ///   Provides data about the event.

        /// </param>

        private void AdornedElement_GotFocus(object sender, RoutedEventArgs e)

        {

            TextBoxBase textBoxBase = AdornedElement as TextBoxBase;

            if (textBoxBase != null)

                textBoxBase.TextChanged -= this.AdornedElement_ContentChanged;

            else

            {

                PasswordBox passwordBox = AdornedElement as PasswordBox;

                if (passwordBox != null)

                    passwordBox.PasswordChanged -= this.AdornedElement_ContentChanged;

            }

 

            if (this.isPlaceholderVisible)

                this.InvalidateVisual();

        }

 

        /// <summary>

        ///   Event handler for AdornedElement.LostFocus.

        /// </summary>

        /// <param name="sender">

        ///   The AdornedElement where the event handler is attached.

        /// </param>

        /// <param name="e">

        ///   Provides data about the event.

        /// </param>

        private void AdornedElement_LostFocus(object sender, RoutedEventArgs e)

        {

            TextBoxBase textBoxBase = AdornedElement as TextBoxBase;

            if (textBoxBase != null)

                textBoxBase.TextChanged += this.AdornedElement_ContentChanged;

            else

            {

                PasswordBox passwordBox = AdornedElement as PasswordBox;

                if (passwordBox != null)

                    passwordBox.PasswordChanged += this.AdornedElement_ContentChanged;

            }

 

            if (!this.isPlaceholderVisible && this.IsElementEmpty())

                this.InvalidateVisual();

        }

 

        /// <summary>

        ///   Event handler for AdornedElement.ContentChanged.

        /// </summary>

        /// <param name="sender">

        ///   The AdornedElement where the event handler is attached.

        /// </param>

        /// <param name="e">

        ///   Provides data about the event.

        /// </param>

        private void AdornedElement_ContentChanged(object sender, RoutedEventArgs e)

        {

            if (this.isPlaceholderVisible ^ this.IsElementEmpty())

                this.InvalidateVisual();

        }

        #endregion

 

        /// <summary>

        ///   Checks if the content of the adorned element is empty.

        /// </summary>

        /// <returns>

        ///   Returns <see langword="true" /> if the content is empty, <see langword="false" /> otherwise.

        /// </returns>

        private bool IsElementEmpty()

        {

            UIElement adornedElement = AdornedElement;

            TextBox textBox = adornedElement as TextBox;

            if (textBox != null)

                return string.IsNullOrEmpty(textBox.Text);

            PasswordBox passwordBox = adornedElement as PasswordBox;

            if (passwordBox != null)

                return string.IsNullOrEmpty(passwordBox.Password);

            RichTextBox richTextBox = adornedElement as RichTextBox;

            if (richTextBox != null)

            {

                BlockCollection blocks = richTextBox.Document.Blocks;

                if (blocks.Count == 0)

                    return true;

                if (blocks.Count == 1)

                {

                    Paragraph paragraph = blocks.FirstBlock as Paragraph;

                    if (paragraph == null)

                        return false;

                    if (paragraph.Inlines.Count == 0)

                        return true;

                    if (paragraph.Inlines.Count == 1)

                    {

                        Run run = paragraph.Inlines.FirstInline as Run;

                        return run != null && string.IsNullOrEmpty(run.Text);

                    }

                }

 

                return false;

            }

 

            return false;

        }

 

        /// <summary>

        ///   Computes the text alignment of the adorned element.

        /// </summary>

        /// <returns>

        ///   Returns the computed text alignment.

        /// </returns>

        private TextAlignment ComputedTextAlignment()

        {

            Control adornedElement = AdornedElement as Control;

            TextBox textBox = adornedElement as TextBox;

            if (textBox != null)

            {

                if (DependencyPropertyHelper.GetValueSource(textBox, TextBox.HorizontalContentAlignmentProperty)

                    .BaseValueSource != BaseValueSource.Local ||

                    DependencyPropertyHelper.GetValueSource(textBox, TextBox.TextAlignmentProperty)

                    .BaseValueSource == BaseValueSource.Local)

 

                    // TextAlignment dominates

                    return textBox.TextAlignment;

            }

 

            RichTextBox richTextBox = adornedElement as RichTextBox;

            if (richTextBox != null)

            {

                BlockCollection blocks = richTextBox.Document.Blocks;

                TextAlignment textAlignment = richTextBox.Document.TextAlignment;

                if (blocks.Count == 0)

                    return textAlignment;

                if (blocks.Count == 1)

                {

                    Paragraph paragraph = blocks.FirstBlock as Paragraph;

                    if (paragraph == null)

                        return textAlignment;

                    return paragraph.TextAlignment;

                }

 

                return textAlignment;

            }

 

            switch (adornedElement.HorizontalContentAlignment)

            {

                case HorizontalAlignment.Left:

                    return TextAlignment.Left;

                case HorizontalAlignment.Right:

                    return TextAlignment.Right;

                case HorizontalAlignment.Center:

                    return TextAlignment.Center;

                case HorizontalAlignment.Stretch:

                    return TextAlignment.Justify;

            }

 

            return TextAlignment.Left;

        }

    }

}