//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//
// UserWin satellite library | Author: Sergei Y.Kitáev
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;

using System.Windows;

using CommonHelpers;

namespace UserWin {

//**************************************************************************************************
/// <summary>
/// </summary>
public delegate void HProcessElementCallback(FrameworkElement element);
//**************************************************************************************************


//**************************************************************************************************
/// <summary>
/// </summary>
public static partial class UXLogicalTreeHelper {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/// <exception cref="HOperationFailedException" />
public static T StrictFindLogicalNode<T>(FrameworkElement root,string elementName)
   where T: FrameworkElement
{
   HArgChecking.VerifyNotNulls( root, elementName );
   var element = LogicalTreeHelper.FindLogicalNode( root, elementName );
   if (element==null)
      throw HOpFailedExceptionCreator.Create(
         "Logical node not found by name: \"{0}\".", elementName );
   if (!(element is T))
      throw HOpFailedExceptionCreator.Create(
         "Named logical node \"{0}\" is not of \"{1}\" type.", elementName, typeof(T) );
   return (T)element;
}

//==================================================================================================

public static void ProcessNodes(FrameworkElement root,HProcessElementCallback callback)
{
   ProcessNodes( root, true, callback );
}

public static void ProcessNodes( FrameworkElement root, bool processRoot,
                                 HProcessElementCallback callback )
{
   ProcessNodes( root, processRoot, true, callback );
   if (processRoot)
      callback(root);
}

public static void ProcessNodes( FrameworkElement root,
                                 bool processRoot, bool recursive,
                                 HProcessElementCallback callback )
{
   ProcessChildren( root, recursive, callback );
   if (processRoot)
      callback(root);
}

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

public static void ProcessChildren(FrameworkElement root,HProcessElementCallback callback)
{
   ProcessChildren( root, true, callback );
}

public static void ProcessChildren( FrameworkElement root, bool recursive,
                                    HProcessElementCallback callback )
{
   foreach (var child in LogicalTreeHelper.GetChildren(root))
   {
      var element = child as FrameworkElement;

      if (element!=null)
      {
         if (recursive)
            ProcessChildren( element, callback );
         callback( element );
      }
   }
}

//==================================================================================================

public static void SetNodeValue(FrameworkElement root,DependencyProperty property,object value)
{
   SetNodeValue( root, true, property, value );
}

public static void SetNodeValue( FrameworkElement root, bool processRoot,
                                 DependencyProperty property, object value )
{
   SetNodeValue( root, processRoot, true, property, value );
}

public static void SetNodeValue( FrameworkElement root, bool processRoot, bool recursive,
                                 DependencyProperty property, object value )
{
   ProcessNodes
   (
      root, processRoot, recursive,
      delegate (FrameworkElement element)
      {
         element.SetValue( property, value );
      }
   );
}

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

public static void SetChildrenValue( FrameworkElement root,
                                     DependencyProperty property,
                                     object value )
{
   SetChildrenValue( root, true, property, value );
}

public static void SetChildrenValue( FrameworkElement root, bool recursive,
                                     DependencyProperty property, object value )
{
   SetNodeValue( root, false, recursive, property, value );
}

//==================================================================================================

public static void ClearNodeValue(FrameworkElement root,DependencyProperty property)
{
   ClearNodeValue( root, true, property );
}

public static void ClearNodeValue( FrameworkElement root,
                                   bool processRoot,
                                   DependencyProperty property )
{
   ClearNodeValue( root, processRoot, true, property );
}

public static void ClearNodeValue( FrameworkElement root,
                                   bool processRoot, bool recursive,
                                   DependencyProperty property )
{
   ProcessNodes
   (
      root, processRoot, recursive,
      delegate (FrameworkElement element)
      {
         element.ClearValue( property );
      }
   );
}

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

public static void ClearChildrenValue(FrameworkElement root,DependencyProperty property)
{
   ClearChildrenValue( root, true, property );
}

public static void ClearChildrenValue( FrameworkElement root,
                                       bool recursive,
                                       DependencyProperty property )
{
   ClearNodeValue( root, false, recursive, property );
}

//==================================================================================================

static UXLogicalTreeHelper()
{
   UserWin_Library.Access();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // UXLogicalTreeHelper
//**************************************************************************************************

} // UserWin
