JavaScript Editor Ajax Editor     Ajax development 



Main Page

Previous Page
Next Page

Appendix B. KPI UtilitiesCode for Parsing Display Folders and Getting Image Indexes

// -----------------------------------------------------
// KpiUtilities
//
// Contains re-usable KPI-related utility functions.
// -----------------------------------------------------

using System;
using System.Collections;
using System.Text;
using System.Windows.Forms;

namespace KpiDemo
{
   public static class KpiUtilities
      {
         /// <summary>
         /// Returns a collection of TreeNodes representing
         ///the display folders contained
         /// in the displayFolders parameter. These TreeNodes
         ///will be created if not found.
         /// An empty array will be returned if displayFolders
         ///does not contain any displayfolders.
         /// </summary>
         /// <param name="rootNodeCollection">nodes collection
         ///to use as the root of the KPI tree</param>
         /// <param name="displayFolders">the value of a
         ///DisplayFolders property</param>
         /// <param name="displayFolderImageIndex">the
         ///ImageIndex to use for a display folder tree node
         ///</param> <returns>
         /// An array of TreeNode objects representing the
         ///display folders contained in displayFolders.
         /// May return an empty array but will not return
         /// null.
         /// </returns>
         public static TreeNode[] GetDisplayFolderTreeNodes(
                TreeNodeCollection rootNodeCollection,
                string displayFolders,
                int displayFolderImageIndex )
         {
            if ( string.IsNullOrEmpty( displayFolders ) )
            {
               return new TreeNode[0];
            }
            else
            {
               string[][] parsedDisplayFolders =
               ParseDisplayFolders( displayFolders );
               int pathCount =
                  parsedDisplayFolders.GetLength( 0 );
               TreeNode[] displayFolderNodes =
                  new TreeNode[pathCount];
               for ( int pathIndex = 0; pathIndex < pathCount;
                         pathIndex++ )
               {
                  string[] path =
                  parsedDisplayFolders[pathIndex];
                  TreeNode folderNode = null;
                  TreeNodeCollection parentNodeCollection =
                     rootNodeCollection;
                  foreach ( string folder in path )
                  {
                     TreeNode[] nodesFound =
                     parentNodeCollection.Find( folder, false );
                     if ( nodesFound.Length > 0 )
                     {
                        folderNode = nodesFound[0];
                     }
                     else
                     {
                        folderNode =
                        parentNodeCollection.Add( folder, folder,
                        displayFolderImageIndex,
                        displayFolderImageIndex );
                     }
                     parentNodeCollection = folderNode.Nodes;
                  }
                  displayFolderNodes[pathIndex] = folderNode;
               }
               return displayFolderNodes;
            }
         }

         /// <summary>
         /// Parses the value of a DisplayFolders property
         /// into an array of paths, each of which is
         /// an array of folder names.
         /// </summary>
         /// <param name="displayFolders">string containing
         /// the value of a DisplayFolders property</param>
         /// <returns>
         /// An array of arrays of strings. The outer array
         /// may be zero-length, but will not be null.
         /// The inner arrays will not be null or
         /// zero-length. Duplicate paths will be removed.
         /// </returns>
         public static string[][]
                ParseDisplayFolders( string displayFolders )
         {
            const char pathDelimiter = ';';
            const char folderDelimiter = '\\';

            if ( displayFolders == null )
            {
               return new string[0][];
            }

            // Get paths
            int emptyPathCount = 0;
            string[] pathStrings =
               displayFolders.Split( pathDelimiter );
            string[][] allPaths =
               new string[pathStrings.Length][];
            for ( int i = 0; i < pathStrings.Length; i++ )
            {
               // Get folders
               int emptyFolderCount = 0;
               string[] allFolders =
                  pathStrings[i].Split( folderDelimiter );
               for ( int j = 0; j < allFolders.Length; j++ )
            {
               allFolders[j] = allFolders[j].Trim();
               if ( allFolders[j].Length == 0 )
               {
                  emptyFolderCount++;
               }
            }

            // Get currentPath without any
            // empty folders
            string[] nonEmptyFolders;
            if ( emptyFolderCount == 0 )
            {
               // This is the common case,
               // so optimize
               nonEmptyFolders = allFolders;
            }
            else if ( emptyFolderCount == allFolders.Length )
            {
               nonEmptyFolders = null;
               emptyPathCount++;
            }
            else
            {
               nonEmptyFolders =
               new string [allFolders.Length 
                          emptyFolderCount];
               for ( int j = 0, k = 0; j <
               allFolders.Length; j++ )
               {
                  if ( allFolders[j].Length > 0 )
                  {
                     nonEmptyFolders[k] = allFolders[j];
                     k++;
                  }
               }
            }

            // Remove duplicate paths
            if ( nonEmptyFolders != null &&
                 IsPathAlreadyInPathsArray( allPaths,
                 nonEmptyFolders, i ) )
            {
               nonEmptyFolders = null;
               emptyPathCount++;
            }
               allPaths[i] = nonEmptyFolders;
            }

            // Get results without any empty paths
            string[][] nonEmptyPaths;
            if ( emptyPathCount == 0 )
            {
               // This is the common case, so optimize
               nonEmptyPaths = allPaths;
            }
            else if ( emptyPathCount == allPaths.Length )
            {
               nonEmptyPaths = new string[0][];
            }
            else
            {
               nonEmptyPaths =
                  new string[allPaths.Length 
                  emptyPathCount][];
               for ( int i = 0, j = 0; i < allPaths.Length; i++ )
               {
                  if ( allPaths[i] != null )
                  {
                     nonEmptyPaths[j] =
                     allPaths[i];
                     j++;
                  }
               }
            }
            return nonEmptyPaths;
         }

         /// <summary>
         /// Takes a normalized value such as those associated
         /// with KPI Status and Trend and returns
         /// a numeric index of an image based on the
         /// normalized value.
         /// </summary>
         /// <param name="normalizedValue">normalized value
         /// between -1 and 1 (values less than -1 are treated
         /// as -1 and those greater than 1 are treated as
         /// 1)</param>
         /// <param name="firstImageIndex">value of the first
         /// image index</param>
         /// <param name="lastImageIndex">value of the last
         /// image index</param>
         /// <returns>An integer between firstImageIndex and
         /// lastImageIndex, inclusive</returns>
         public static int GetImageIndex( double normalizedValue,
            int firstImageIndex, int lastImageIndex )
         {
            const double normalizedLowerBound = -1.0;
            const double normalizedUpperBound = 1.0;
            if ( double.IsNaN( normalizedValue ) )
            {
               return firstImageIndex;
            }
            else if ( normalizedValue <= -1 )
            {
               return firstImageIndex;
            }
            else if ( normalizedValue >= 1 )
            {
               return lastImageIndex;
            }
            else
            {
               const double inputRange =
                  normalizedUpperBound 
                  normalizedLowerBound;
               double outputRange =
                      ( double )( Math.Abs( lastImageIndex 
                      firstImageIndex ) + 1 );
               double outputSegmentsFromLowerBound =
                      ( normalizedValue - normalizedLowerBound )
                      * ( outputRange / inputRange );
               outputSegmentsFromLowerBound =
                  Math.Round( outputSegmentsFromLowerBound,
                  10 ); // round off floating point errors
                  int zeroBasedIndex = ( int )(
                     ( normalizedValue > 0 ) ?
                     Math.Floor( outputSegmentsFromLowerBound):
                     // borders between segments (whole
                     //numbers) belong to the preceeding
                     // segment
                     Math.Ceiling(
                     outputSegmentsFromLowerBound ) - 1 );
                     // borders between segments (whole
                     // numbers) belong to the following
                     // segment

                  return ( firstImageIndex < lastImageIndex )?
                         firstImageIndex + zeroBasedIndex :
                         firstImageIndex - zeroBasedIndex;
            }
         }

         #region ParseDisplayFolder helper methods

         /// <summary>
         /// Checks whether paths contains currentPath before
         /// currentIndex. Used by ParseDisplayFolders.
         /// </summary>
         private static bool IsPathAlreadyInPathsArray(
            string[][] paths,
         string[] currentPath,
            int currentIndex )
         {
            if ( paths == null )
            {
                 return false;
            }

            int count =
               Math.Min( currentIndex, paths.GetLength( 0 ) );
               for ( int i = 0; i < count; i++ )
               {
                  if ( DoPathsMatch( paths[i], currentPath ) )
                  {
                     return true;
                  }
               }
               return false;
         }

         /// <summary>
         /// Checks whether path1 and path2 match.
         /// </summary>
         private static bool
                 DoPathsMatch( string[] path1, string[] path2 )
         {
              if ( path1 == null && path2 == null )
              {
                 return true;
              }
              else if ( path1 == null || path2 == null )
              {
                 return false;
              }
              else if ( path1.Length != path2.Length )
              {
                 return false;
              }
              else
              {
                 for ( int i = 0; i < path1.Length; i++ )
                 {
                    if ( string.Compare( path1[i],
                       path2[i], true,System.Globalization.
                       CultureInfo.CurrentUICulture )
                       != 0 )
                    {
                       return false;
                    }
                 }
                 return true;
              }
        }
        #endregion ParseDisplayFolder helper methods
     }
}


Previous Page
Next Page


JavaScript Editor Ajax Editor     Ajax development