PHP Classes
Icontem

File: class.diagram.php


  Search   All class groups All class groups   Latest entries Latest entries   Top 10 charts Top 10 charts   Newsletter Newsletter   Blog Blog   Forums Forums   Help FAQ Help FAQ  
  Login   Register  
Recommend this page to a friend! ReTweet ReTweet Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Diogo Resende  >  Diagram 2  >  class.diagram.php  
File: class.diagram.php
Role: Class source
Content type: text/plain
Description: Main class
Class: Diagram 2
Draw an hierarchic diagram from a XML definition
 

Contents

Class file image Download
<?php
    /**
     * Diagram
     * Class to draw diagrams from a xml file/data
     *
     * @author Diogo Resende <me@diogoresende.net>
     * @version 2.0
     * @
     *
     **/
    class Diagram {
        var $prepared = false;
        
        var $padding = array(
            'top'    => 2,
            'left'   => 2,
            'right'  => 2,
            'bottom' => 2
        );
        var $margin = array(
            'top'    => 10,
            'left'   => 10,
            'right'  => 10,
            'bottom' => 10
        );
        var $border = array(
            'top'        => 1,
            'left'       => 1,
            'right'      => 1,
            'bottom'     => 1,
            'middle'     => 1,
            'connection' => 1
        );
        var $color = array(
            'background' => '#f',
            'border'     => '#0',
            'connection' => '#0',
            'name'       => array(
                'background' => '#f4f4f4',
                'text'       => '#0',
                'connection' => '#0'
            ),
            'data'       => array(
                'background' => '#f0f0f0',
                'text'       => '#0'
            )
        );
        var $font = array(
            'name'       => 3,
            'data'       => 2,
            'connection' => 2
        );
        var $align = array(
            'name' => 'left',
            'data' => 'left'
        );
        var $width = 100;
        
        /**
         * If this is true, the node will have the width necessary
         * to show the name in only one line. It will still have the
         * normal width if the name is small
         **/
        var $fit_name = true;

        /**
         * If zero, no arrow is drawed, if greather than zero, an
         * arrow will be drawed with that size
         **/
        var $arrow_thickness = 3;
        
        /**
         * Diagram::Diagram()
         *
         * Class constructor
         **/
        function Diagram($xml_file = '') {
            if (strlen($xml_file) > 0) {
                $this->loadXmlFile($xml_file);
            }
        }

        /**
         * Diagram::loadXmlFile()
         *
         * Load data from XML file
         **/
        function loadXmlFile($file) {
            if (($fp = fopen($file, 'r')) !== false) {
                $data = '';
                while (!feof($fp)) {
                    $data .= fread($fp, 4096);
                }
                fclose($fp);

                $this->loadXmlData($data);
            }
        }

        /**
         * Diagram::loadXmlData()
         *
         * Load data from a XML string
         **/
        function loadXmlData($data) {
            if (!class_exists('XmlParser')) {
                /*...............**/
                require dirname(__FILE__) . '/class.xmlparser.php';
            }
            $xml = new XmlParser($data);

            $this->struct = $xml->struct;

            $xml = null;
            
            $this->prepared = false;
        }
        
        /**
         * Diagram::loadFromArray()
         *
         * Load data from an associative array
         **/
        function loadFromArray($array) {
            $this->struct = array(array('childs' => array()));
            $this->__addArrayToNode($this->struct[0]['childs'], $array);
        }

        /**
         * Diagram::setDefaultBorder()
         *
         * Set border sizes. You can omit borders. The ones available are:
         * - left,top,right,bottom,middle,connection
         *
         * Example: setDefaultBorder(array('left' => 2, 'right' => 2));
         **/
        function setDefaultBorder($borders) {
            foreach ($borders as $k => $v) {
                if (isset($this->border[$k])) {
                    $this->border[$k] = (int) $v;
                }
            }
        }
        
        /**
         * Diagram::setDefaultFont()
         *
         * Set fonts. You can omit fonts. The ones available are:
         * - name,data,connection
         *
         * Example: setDefaultFont(array('connection' => 1, 'name' => 2, 'data' => 3));
         **/
        function setDefaultFont($fonts) {
            foreach ($fonts as $k => $v) {
                if (isset($this->font[$k])) {
                    $this->font[$k] = $v;
                }
            }
        }
        
        /**
         * Diagram::setDefaultAlign()
         *
         * Set alignments. You can omit alignments. The ones available are:
         * - name,data
         * The possible alignments are:
         * - left,center,right
         *
         * Example: setDefaultAlign(array('name' => 'center'));
         **/
        function setDefaultAlign($aligns) {
            foreach ($aligns as $k => $v) {
                if (isset($this->align[$k])) {
                    $this->align[$k] = $v;
                }
            }
        }

        /**
         * Diagram::setDefaultColor()
         *
         * Set colors. You can omit colors. The ones available are:
         * - background,border,connection
         *
         * Example: setDefaultColor(array('background' => '#ffffff', 'border' => '#000'));
         **/
        function setDefaultColor($colors) {
            foreach ($colors as $k => $v) {
                if (isset($this->color[$k])) {
                    $this->color[$k] = $v;
                }
            }
        }
        
        /**
         * Diagram::setDefaultDataColor()
         *
         * Set data colors. You can omit colors. The ones available are:
         * - background,text
         *
         * Example: setDefaultDataColor(array('text' => '#000'));
         **/
        function setDefaultDataColor($colors) {
            foreach ($colors as $k => $v) {
                if (isset($this->color['data'][$k])) {
                    $this->color['data'][$k] = $v;
                }
            }
        }
        
        /**
         * Diagram::setDefaultNameColor()
         *
         * Set name colors. You can omit colors. The ones available are:
         * - background,text,connection
         *
         * Example: setDefaultNameColor(array('text' => '#000'));
         **/
        function setDefaultNameColor($colors) {
            foreach ($colors as $k => $v) {
                if (isset($this->color['name'][$k])) {
                    $this->color['name'][$k] = $v;
                }
            }
        }

        /**
         * Diagram::Draw()
         *
         * Draw all the diagram and output it to stdout
         * or a file
         **/
        function Draw($output_file = '') {
            if (!$this->prepared) {
                $this->__prepare($this->struct[0], true);
                $this->prepared = true;
            }

            $w = $this->struct[0]['attrib']['TOTALWIDTH'];
            $h = $this->struct[0]['attrib']['CHILDHEIGHT'];
            
            $im = imagecreatetruecolor($w, $h);

            $this->__drawBackground($im, $this->struct[0]['attrib'], $w, $h);
            $this->__drawNode($im, $this->struct[0]['childs'][0], 0, 0, $this->struct[0]['childs'][0]['attrib']['NODEHEIGHT']);
            
            /**
             * Output
             **/
            if (strlen($output_file) > 0 && is_dir(dirname($output_file))) {
                imagepng($im, $output_file);
            } else {
                header('Content-Type: image/png');
                imagepng($im);
            }
        }

        /**
         * Diagram::__addArrayToNode()
         *
         * Load an array to a node with default values
         **/
        function __addArrayToNode(&$node_childs, &$array) {
            foreach ($array as $k => $v) {
                if (is_array($v)) {
                    $node_childs[] = array(
                        'tag'    => 'NODE',
                        'attrib' => array(),
                        'data'   => $k,
                        'childs' => array()
                    );
                    $this->__addArrayToNode($node_childs[count($node_childs) - 1]['childs'], $v);
                } else {
                    $node_childs[] = array(
                        'tag'    => 'NODE',
                        'attrib' => array(),
                        'data'   => $v,
                        'childs' => array()
                    );
                }
            }
        }

        /**
         * Diagram::__drawBackground()
         *
         * Draw diagram background
         **/
        function __drawBackground(&$im, &$diagram_atr, $w, $h) {
            if (isset($diagram_atr['BGCOLOR2'])) {
                $this->__drawDegrade($im, 0, 0, $w, $h, $diagram_atr['BGCOLOR'], $diagram_atr['BGCOLOR2']);
            } else {
                $c = $this->__allocateColor($im, $diagram_atr['BGCOLOR']);
                
                imagefilledrectangle($im, 0, 0, $w, $h, $c);
            }
        }

        /**
         * Diagram::__drawNode()
         *
         * Draw a node
         **/
        function __drawNode(&$im, &$node, $left = 0, $top = 0, $total_height = 0, $parent_tail_left = null, $parent_tail_top = null) {
            $x = round(($node['attrib']['TOTALWIDTH'] - $node['attrib']['NODEWIDTH']) / 2);
            
            $x += $left + $node['attrib']['MARGINLEFT'];
            $y = $top + $node['attrib']['MARGINTOP'];
            
            $this->__drawNodeBackground($im, $node['attrib'], $x, $y, (strlen($node['data']) > 0));
            $this->__drawNodeBorder($im, $node['attrib'], $x, $y, (strlen($node['data']) > 0));
            
            if ($parent_tail_left != null) {
                $this->__drawNodeParentConnection($im,
                                                  $node,
                                                  $x + round($node['attrib']['WIDTH'] / 2),
                                                  $y,
                                                  $parent_tail_left,
                                                  $parent_tail_top,
                                                  $node['attrib']['CONNECTIONCOLOR'],
                                                  $node['attrib']['BORDERCONNECTION'],
                                                  $node['attrib']['ARROW']);
            }
            $this->__drawNodeData($im, $node, $x, $y);

            $node_tail_left = ($left + round($node['attrib']['TOTALWIDTH'] / 2));
            $node_tail_top = ($top + $node['attrib']['NODEHEIGHT'] - $node['attrib']['MARGINBOTTOM']);

            $left_offset = $left;
            $top_offset = $top + $total_height;
            for ($i = 0; $i < count($node['childs']); $i++) {
                $this->__drawNode($im, $node['childs'][$i], $left_offset, $top_offset, $node['attrib']['TOTALHEIGHT'], $node_tail_left, $node_tail_top);
                
                $left_offset += $node['childs'][$i]['attrib']['TOTALWIDTH'];
            }
        }

        function __drawNodeParentConnection(&$im, &$node, $node_tail_left, $node_tail_top, $parent_tail_left, $parent_tail_top, $color, $thickness, $arrow_thickness) {
            $offset = round($thickness / 2);
            $middle = round(($node_tail_top - $parent_tail_top) / 2);
            
            $c = $this->__allocateColor($im, $color);
            
            for ($i = 0; $i < $thickness; $i++) {
                imageline($im, $parent_tail_left - $offset + $i, $parent_tail_top, $parent_tail_left - $offset + $i, $parent_tail_top + $middle, $c);
            }
            
            for ($i = 0; $i < $thickness; $i++) {
                imageline($im, $parent_tail_left - $offset, $parent_tail_top + $middle - $i, $node_tail_left - $offset, $parent_tail_top + $middle - $i, $c);
            }
            $j = $i;

            for ($i = 0; $i < $thickness; $i++) {
                imageline($im, $node_tail_left - $offset + $i, $parent_tail_top + $middle - $j + 1, $node_tail_left - $offset + $i, $node_tail_top - $arrow_thickness, $c);
            }
            
            /**
             * Arrow
             **/
            imagesetpixel($im, $node_tail_left - 1, $node_tail_top - 1, $c);
            $offset += $arrow_thickness - 1;
            for ($i = 0; $i < $offset; $i++) {
                imageline($im, $node_tail_left - 2 - $i, $node_tail_top - 2 - $i, $node_tail_left + $i, $node_tail_top - 2 - $i, $c);
            }

            /**
             * Connection text
             **/
            if (isset($node['attrib']['CONNECTIONNAME']) && strlen($node['attrib']['CONNECTIONNAME']) > 0) {
                if ($parent_tail_left > $node_tail_left) {
                    $tmp = $parent_tail_left;
                    $parent_tail_left = $node_tail_left;
                    $node_tail_left = $tmp;
                }
                $this->__drawText($im, $parent_tail_left, $parent_tail_top + $middle - $thickness - imagefontheight($node['attrib']['CONNECTIONFONT']), ($node_tail_left - $parent_tail_left), $node['attrib']['CONNECTIONFONT'], $node['attrib']['CONNECTIONNAMECOLOR'], 'center', $node['attrib']['CONNECTIONNAME']);
            }
        }

        /**
         * Diagram::__drawNodeData()
         *
         * Draw the text on the node
         **/
        function __drawNodeData(&$im, &$node, $left, $top) {
            $left += $node['attrib']['BORDERLEFT'] + $node['attrib']['PADDINGLEFT'];
            $top += $node['attrib']['BORDERTOP'] + $node['attrib']['PADDINGTOP'];
            if (isset($node['attrib']['NAME'])) {
                $top = $this->__drawText($im, $left, $top, $node['attrib']['WIDTH'], $node['attrib']['NAMEFONT'], $node['attrib']['NAMECOLOR'], $node['attrib']['NAMEALIGN'], $node['attrib']['NAME']);
                
                $top += $node['attrib']['PADDINGBOTTOM'] + $node['attrib']['BORDERMIDDLE'] + $node['attrib']['PADDINGTOP'];
            }
            if (strlen($node['data']) > 0) {
                $this->__drawText($im, $left, $top, $node['attrib']['WIDTH'], $node['attrib']['FONT'], $node['attrib']['COLOR'], $node['attrib']['ALIGN'], $node['data']);
            }
        }
        
        /**
         * Diagram::__drawText()
         *
         * Draw text on a certain position with a maximum with, font
         * and color
         * Returns the new vertical position
         **/
        function __drawText(&$im, $x, $y, $max_width, $font, $color, $align, $text) {
            $text = explode("\n", wordwrap($text, floor($max_width / imagefontwidth($font)), "\n"));
            $c = $this->__allocateColor($im, $color);
            for ($i = 0; $i < count($text); $i++) {
                switch ($align) {
                    case 'center':
                        imagestring($im, $font, $x + round(($max_width - (imagefontwidth($font) * strlen($text[$i]))) / 2), $y, $text[$i], $c);
                        break;
                    case 'right':
                        imagestring($im, $font, $x + $max_width - (imagefontwidth($font) * strlen($text[$i])), $y, $text[$i], $c);
                        break;
                    default:
                        imagestring($im, $font, $x, $y, $text[$i], $c);
                }
                $y += imagefontheight($font);
            }
            return $y;
        }
        
        /**
         * Diagram::__drawNodeBorder()
         *
         * Draw the node border
         **/
        function __drawNodeBorder(&$im, &$node_atr, $left, $top, $has_data) {
            $width = $node_atr['BORDERLEFT'] + $node_atr['PADDINGLEFT'] + $node_atr['WIDTH'] + $node_atr['PADDINGRIGHT'];
            $height = $node_atr['BORDERTOP'] + $node_atr['PADDINGTOP'] + $node_atr['HEIGHT'] + $node_atr['PADDINGBOTTOM'];
            
            $c = $this->__allocateColor($im, $node_atr['BORDERCOLOR']);

            for ($i = 0; $i < $node_atr['BORDERLEFT']; $i++) {
                imageline($im, $left + $i, $top, $left + $i, $top + $height - 1, $c);
            }
            
            for ($i = 0; $i < $node_atr['BORDERTOP']; $i++) {
                imageline($im, $left, $top + $i, $left + $width - 1, $top + $i, $c);
            }

            for ($i = 0; $i < $node_atr['BORDERRIGHT']; $i++) {
                imageline($im, $left + $width - $i, $top, $left + $width - $i, $top + $height, $c);
            }
            
            for ($i = 0; $i < $node_atr['BORDERBOTTOM']; $i++) {
                imageline($im, $left, $top + $height + $i, $left + $width, $top + $height + $i, $c);
            }
            
            if ($has_data && isset($node_atr['NAMEHEIGHT'])) {
                $height = $node_atr['BORDERTOP'] + $node_atr['PADDINGTOP'] + $node_atr['NAMEHEIGHT'] + $node_atr['PADDINGBOTTOM'];
                for ($i = 0; $i < $node_atr['BORDERMIDDLE']; $i++) {
                    imageline($im, $left, $top + $height + $i, $left + $width, $top + $height + $i, $c);
                }
            }
        }

        /**
         * Diagram::__drawNodeBackground()
         *
         * Draw the node background(s)
         **/
        function __drawNodeBackground(&$im, &$node_atr, $left, $top, $has_data) {
            $width = $node_atr['BORDERLEFT'] + $node_atr['PADDINGLEFT'] + $node_atr['WIDTH'] + $node_atr['PADDINGRIGHT'];
            $height = $node_atr['BORDERTOP'] + $node_atr['PADDINGTOP'] + $node_atr['HEIGHT'] + $node_atr['PADDINGBOTTOM'];

            if ($has_data) {
                if (isset($node_atr['BGCOLOR2'])) {
                    $this->__drawDegrade($im, $left, $top, $left + $width, $top + $height, $node_atr['BGCOLOR'], $node_atr['BGCOLOR2']);
                } else {
                    $c = $this->__allocateColor($im, $node_atr['BGCOLOR']);
                    imagefilledrectangle($im, $left, $top, $left + $width, $top + $height, $c);
                }
            }
            if (isset($node_atr['NAMEHEIGHT'])) {
                $height = $node_atr['BORDERTOP'] + $node_atr['PADDINGTOP'] + $node_atr['NAMEHEIGHT'] + $node_atr['PADDINGBOTTOM'];

                if (isset($node_atr['NAMEBGCOLOR2'])) {
                    $this->__drawDegrade($im, $left, $top, $left + $width, $top + $height, $node_atr['NAMEBGCOLOR'], $node_atr['NAMEBGCOLOR2']);
                } else {
                    $c = $this->__allocateColor($im, $node_atr['NAMEBGCOLOR']);
                    imagefilledrectangle($im, $left, $top, $left + $width, $top + $height, $c);
                }
            }
        }

        /**
         * Diagram::__prepare()
         *
         * Prepare the diagram structure and add the individual
         * settings to every node
         **/
        function __prepare(&$node, $is_diagram = false) {
            /**
             * Padding
             **/
            if ($this->__checkParam($node['attrib'], 'PADDING')) {
                /**
                 * this ensures that if there is a global atribute for
                 * padding, it is spreaded thru all paddings
                 **/
                $this->__setParam($node['attrib'],
                                  array(
                                    'PADDINGLEFT',
                                    'PADDINGTOP',
                                    'PADDINGRIGHT',
                                    'PADDINGBOTTOM'
                                  ),
                                  $node['attrib']['PADDING']);
            }
            $this->__checkParam($node['attrib'], 'PADDINGLEFT', $this->padding['left']);
            $this->__checkParam($node['attrib'], 'PADDINGTOP', $this->padding['top']);
            $this->__checkParam($node['attrib'], 'PADDINGRIGHT', $this->padding['right']);
            $this->__checkParam($node['attrib'], 'PADDINGBOTTOM', $this->padding['bottom']);

            /**
             * Borders
             **/
            if ($this->__checkParam($node['attrib'], 'BORDER')) {
                /**
                 * this ensures that if there is a global atribute for
                 * border, it is spreaded thru all borders
                 **/
                $this->__setParam($node['attrib'],
                                  array(
                                    'BORDERLEFT',
                                    'BORDERTOP',
                                    'BORDERRIGHT',
                                    'BORDERBOTTOM',
                                    'BORDERMIDDLE',
                                    'BORDERCONNECTION'
                                  ),
                                  $node['attrib']['BORDER']);
            }
            $this->__checkParam($node['attrib'], 'BORDERLEFT', $this->border['left']);
            $this->__checkParam($node['attrib'], 'BORDERTOP', $this->border['top']);
            $this->__checkParam($node['attrib'], 'BORDERRIGHT', $this->border['right']);
            $this->__checkParam($node['attrib'], 'BORDERBOTTOM', $this->border['bottom']);
            $this->__checkParam($node['attrib'], 'BORDERMIDDLE', $this->border['middle']);
            $this->__checkParam($node['attrib'], 'BORDERCONNECTION', $this->border['connection']);

            /**
             * Margins
             **/
            if ($this->__checkParam($node['attrib'], 'MARGIN')) {
                /**
                 * this ensures that if there is a global atribute for
                 * margin, it is spreaded thru all margins
                 **/
                $this->__setParam($node['attrib'],
                                  array(
                                    'MARGINLEFT',
                                    'MARGINTOP',
                                    'MARGINRIGHT',
                                    'MARGINBOTTOM'
                                  ),
                                  $node['attrib']['MARGIN']);
            }
            $this->__checkParam($node['attrib'], 'MARGINLEFT', $this->margin['left']);
            $this->__checkParam($node['attrib'], 'MARGINTOP', $this->margin['top']);
            $this->__checkParam($node['attrib'], 'MARGINRIGHT', $this->margin['right']);
            $this->__checkParam($node['attrib'], 'MARGINBOTTOM', $this->margin['bottom']);
            if (!$is_diagram) {
                /**
                 * Alignments
                 **/
                $this->__checkParam($node['attrib'], 'NAMEALIGN', $this->align['name']);
                $this->__checkParam($node['attrib'], 'ALIGN', $this->align['data']);
            
                /**
                 * Colors
                 **/
                $this->__checkColorParam($node['attrib'], 'NAMECOLOR', $this->color['name']['text']);
                $this->__checkColorParam($node['attrib'], 'NAMEBGCOLOR', $this->color['name']['background']);
                $this->__checkColorParam($node['attrib'], 'COLOR', $this->color['data']['text']);
                $this->__checkColorParam($node['attrib'], 'BGCOLOR', $this->color['data']['background']);
                $this->__checkColorParam($node['attrib'], 'BORDERCOLOR', $this->color['border']);
                $this->__checkColorParam($node['attrib'], 'CONNECTIONCOLOR', $this->color['connection']);
                $this->__checkColorParam($node['attrib'], 'CONNECTIONNAMECOLOR', $this->color['name']['connection']);

                /**
                 * Colors (Degrade support)
                 **/
                if (isset($node['attrib']['BGCOLOR2'])) {
                    $this->__checkColorParam($node['attrib'], 'BGCOLOR2', '');
                }
                if (isset($node['attrib']['NAMEBGCOLOR2'])) {
                    $this->__checkColorParam($node['attrib'], 'NAMEBGCOLOR2', '');
                }

                /**
                 * Fonts
                 **/
                $this->__checkParam($node['attrib'], 'NAMEFONT', $this->font['name']);
                $this->__checkParam($node['attrib'], 'CONNECTIONFONT', $this->font['connection']);
                $this->__checkParam($node['attrib'], 'FONT', $this->font['data']);

                /**
                 * Misc
                 **/
                $this->__checkParam($node['attrib'], 'ARROW', $this->arrow_thickness);
                $this->__checkBooleanParam($node['attrib'], 'FITNAME', $this->fit_name);
                $this->__checkParam($node['attrib'], 'CONNECTIONNAME', '');
            } else {
                /**
                 * Colors
                 **/
                $this->__checkColorParam($node['attrib'], 'BGCOLOR', $this->color['background']);

                /**
                 * Colors (Degrade support)
                 **/
                if (isset($node['attrib']['BGCOLOR2'])) {
                    $this->__checkColorParam($node['attrib'], 'BGCOLOR2', '');
                }

                /**
                 * Global node dimensions
                 **/
                if (isset($node['attrib']['WIDTH']) && (int) $node['attrib']['WIDTH'] > 0) {
                    $this->width = (int) $node['attrib']['WIDTH'];
                }
                
                /**
                 * Global alignments
                 **/
                if (isset($node['attrib']['ALIGN'])) {
                    $this->align['data'] = $node['attrib']['ALIGN'];
                }
                if (isset($node['attrib']['NAMEALIGN'])) {
                    $this->align['name'] = $node['attrib']['NAMEALIGN'];
                }
            }
            /**
             * Node dimensions
             **/
            $this->__checkParam($node['attrib'], 'WIDTH', $this->width);
            $this->__calculateNodeWidth($node['attrib']);
            $this->__calculateNodeHeight($node['attrib'], $node['data']);

            $node_width = 0;
            $node_height = 0;
            $child_height = 0;

            for ($i = 0; $i < count($node['childs']); $i++) {
                $this->__prepare($node['childs'][$i]);

                $node_width += $node['childs'][$i]['attrib']['TOTALWIDTH'];
                if ($node['childs'][$i]['attrib']['CHILDHEIGHT'] > $child_height) {
                    $child_height = $node['childs'][$i]['attrib']['CHILDHEIGHT'];
                }
                if ($node['childs'][$i]['attrib']['NODEHEIGHT'] > $node_height) {
                    $node_height = $node['childs'][$i]['attrib']['NODEHEIGHT'];
                }
            }

            $node['attrib']['TOTALHEIGHT'] = $node_height;
            $node['attrib']['CHILDHEIGHT'] = $node['attrib']['TOTALHEIGHT'] + $child_height;

            if ($node_width > $node['attrib']['NODEWIDTH']) {
                $node['attrib']['TOTALWIDTH'] = $node_width;
            } else {
                $node['attrib']['TOTALWIDTH'] = $node['attrib']['NODEWIDTH'];
            }
        }

        /**
         * Diagram::__drawDegrade()
         *
         * Draw a degrade from a color to another inside a rectangle
         **/
        function __drawDegrade(&$im, $x1, $y1, $x2, $y2, $color_start, $color_end) {
            $steps = ($y2 - $y1);
            $inc_r = ($color_end[0] - $color_start[0]) / $steps;
            $inc_g = ($color_end[1] - $color_start[1]) / $steps;
            $inc_b = ($color_end[2] - $color_start[2]) / $steps;
            
            $c = $color_start;
            while ($y2 > $y1) {
                $c[0] += $inc_r;
                $c[1] += $inc_g;
                $c[2] += $inc_b;
                //print_r($c);
                $cl = $this->__allocateColor($im, $c);
                imageline($im, $x1, $y1, $x2, $y1++, $cl);
            }
        }
        
        /**
         * Diagram::__totalLines()
         *
         * Returns the number of lines that a certain amount of
         * text needs with a certain font and a certain maximum
         * width
         **/
        function __totalLines($text, $font, $max_width) {
            $text = wordwrap($text, floor($max_width / imagefontwidth($font)), "\n");

            return substr_count($text, "\n") + 1;
        }
        
        /**
         * Diagram::__calculateNodeWidth()
         *
         * Based on Diagram::fit_title and node atributes, this
         * function returns the width of the node (not including
         * paddings, margins or borders)
         **/
        function __calculateNodeWidth(&$node_atr) {
            if (isset($node_atr['NAME']) && strlen($node_atr['NAME']) > 0 && $node_atr['FITNAME']) {
                /**
                 * Node wants it's title to fit in one line
                 **/
                $w = strlen($node_atr['NAME']) * imagefontwidth($node_atr['NAMEFONT']);
                if ($node_atr['WIDTH'] < $w) {
                    $node_atr['WIDTH'] = $w;
                }
            } else {
                $this->__checkParam($node_atr, 'WIDTH', $this->width);
            }
            $node_atr['NODEWIDTH'] = $node_atr['MARGINLEFT'] + $node_atr['BORDERLEFT'] + $node_atr['PADDINGLEFT'] +
                                     $node_atr['WIDTH'] +
                                     $node_atr['PADDINGRIGHT'] + $node_atr['BORDERRIGHT'] + $node_atr['MARGINRIGHT'];
        }

        /**
         * Diagram::__calculateNodeHeight()
         *
         * Based on node width, it returns the height (including
         * middle border and 1 padding top and 1 padding bottom
         *   ____|____
         *  |_________| <--- from here (top of title)
         *  |         |
         *  |         |
         *  |_________| <--- to here (bottom of data)
         **/
        function __calculateNodeHeight(&$node_atr, &$node_data) {
            $height = 0;
            /**
             * Name
             **/
            if (isset($node_atr['NAME'])) {
                /**
                 * At least it will fill one line
                 **/
                $height = imagefontheight($node_atr['NAMEFONT']);
                if (!$node_atr['FITNAME']) {
                    /**
                     * Multiply the size of one line by the number of lines
                     **/
                    $height *= $this->__totalLines($node_atr['NAME'], $node_atr['NAMEFONT'], $node_atr['WIDTH']);
                }
                $this->__setParam($node_atr, 'NAMEHEIGHT', $height);
            }
            
            /**
             * Data
             **/
            if (strlen($node_data) > 0) {
                if (isset($node_atr['NAME'])) {
                    $height += $node_atr['PADDINGBOTTOM'] + $node_atr['BORDERMIDDLE'] + $node_atr['PADDINGTOP'];
                }
                $height += (imagefontheight($node_atr['FONT']) * $this->__totalLines($node_data, $node_atr['FONT'], $node_atr['WIDTH']));
            }
            
            $node_atr['HEIGHT'] = $height;
            $node_atr['NODEHEIGHT'] = $node_atr['MARGINTOP'] + $node_atr['BORDERTOP'] + $node_atr['PADDINGTOP'] +
                                      $node_atr['HEIGHT'] +
                                      $node_atr['PADDINGBOTTOM'] + $node_atr['BORDERBOTTOM'] + $node_atr['MARGINBOTTOM'];
        }
        
        /**
         * Diagram::__checkParam()
         *
         * Check for existance of a parameter in a node and atribute
         * the default one if not found.
         * If default_value is null it returns only the existance of
         * the parameter
         **/
        function __checkParam(&$atributes, $param, $default_value = null) {
            if ($default_value == null) {
                return isset($atributes[$param]);
            } elseif (!isset($atributes[$param])) {
                $atributes[$param] = $default_value;
                return false;
            }
            return true;
        }
        
        /**
         * Diagram::__checkColorParam()
         *
         * Checks the parameter with Diagram::__checkParam() and
         * then converts it to a color array
         **/
        function __checkColorParam(&$atributes, $param, $default_value) {
            if (!isset($atributes[$param])) {
                $atributes[$param] = $default_value;
            }
            $atributes[$param] = $this->__decodeRgbColor($atributes[$param]);
        }

        /**
         * Diagram::__checkBooleanParam()
         *
         * Checks the parameter with Diagram::__checkParam() and
         * then converts it to a boolean
         **/
        function __checkBooleanParam(&$atributes, $param, $default_value) {
            if (!isset($atributes[$param])) {
                $atributes[$param] = (bool) $default_value;
            } else {
                $atributes[$param] = (bool) $atributes[$param];
            }
        }

        /**
         * Diagram::__setParam()
         *
         * Set a value to a parameter or an array of parameters
         **/
        function __setParam(&$node_attributes, $atribute_name, $value) {
            if (is_array($atribute_name)) {
                for ($i = 0; $i < count($atribute_name); $i++) {
                    $node_attributes[$atribute_name[$i]] = $value;
                }
            } else {
                $node_attributes[$atribute_name] = $value;
            }
        }
        
        /**
         * Diagram::__decodeRgbColor()
         *
         * Given an RGB string (#abcdef, #abc, #a) returns an array
         * with the Red, Green and Blue componements
         **/
        function __decodeRgbColor($color) {
            if (preg_match('/^\#[0-9a-f]+$/', $color)) {
                $color = substr($color, 1);
                switch (strlen($color)) {
                    case 6:
                        return array(hexdec(substr($color, 0, 2)),
                                     hexdec(substr($color, 2, 2)),
                                     hexdec(substr($color, 4)));
                    case 3:
                        return array(hexdec($color[0] . $color[0]),
                                     hexdec($color[1] . $color[1]),
                                     hexdec($color[2] . $color[2]));
                    case 1:
                        return array(hexdec($color[0] . $color[0]),
                                     hexdec($color[0] . $color[0]),
                                     hexdec($color[0] . $color[0]));
                    default:
                        return array(0, 0, 0); // black
                }
            } else {
                return array(0, 0, 0); // black
            }
        }

        /**
         * Diagram::__allocateColor()
         *
         * Allocate a color on the diagram image or return a pointer
         * if the color is already allocated
         **/
        function __allocateColor(&$im, $color) {
            $c = imagecolorexact($im, $color[0], $color[1], $color[2]);
            if ($c >= 0) {
                return $c;
            }
            return imagecolorallocate($im, $color[0], $color[1], $color[2]);
        }
    }
?>

 
  Advertise on this site Advertise on this site   Site map Site map   Statistics Statistics   Site tips Site tips   Privacy policy Privacy policy   Contact Contact  

For more information send a message to :
info at phpclasses dot org.
Copyright (c) Icontem 1999-2009 PHP Classes - PHP Class Scripts
  PHP Book Reviews - Reviews of books and other products