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

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