Location: PHPKode > projects > ColGUI > wp-content/plugins/gladeToJS/gladeNoJStest.php
<?php

//    Copyright 2006 Alexei Samoylov
//    
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//    
//    http://www.apache.org/licenses/LICENSE-2.0
//    
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions
//    and limitations under the License.


// Description: This file is very similar to gladeToJS except it does not generate
//              any Javascript to go along with the html elements.
//              Instead, the widgets are rendered statically.  The file is used on
//              Wordpress pages to show a preview of the Glade layout.


    // global vars to keep track of size of the client window
    /*$totalX = 0;
    $totalY = 0;
    $maxX = 600;
    $maxY = 480;
    $widthRequest = 0;
    $heightRequest = 0;
    $largestPackingNode;*/
    //$oneBigString='';
               
    // --- NEW DOM-BASED PARSER ---
    
    // takes in a widget and returns its title
    function getWidgetTitle($widget) {
        $nameAttribute = 'blah';                    // some default value
        
        // for windows use the following...
        if($widget->getAttribute('class') == 'GtkWindow') $nameAttribute = 'title';
        // for buttons and labels labels use the following..
        else if($widget->getAttribute('class') == 'GtkButton' || $widget->getAttribute('class') == 'GtkLabel'
        || $widget->getAttribute('class') == 'GtkRadioButton' || $widget->getAttribute('class') == 'GtkCheckButton') $nameAttribute = 'label';
        // for input fields
        if($widget->getAttribute('class') == 'GtkEntry') $nameAttribute = 'text';
        
        $elementList = $widget->childNodes;                            // extract widget properties
        foreach($elementList as $list) {
            if($list->hasAttributes()) {
                if($list->getAttribute('name') == $nameAttribute) {            // find title of widget
                    return $list->nodeValue;
                }
            }
        }
        return "";
    }

    function getWidgetID($widget) {
        return $widget->getAttribute('id');
    }
    
    // this function parses the widget
    function parseWidget($widget) {
        $propertiesArr;                     // declare a properties array
        
        // get properties
        if ($widget->hasChildNodes()) {
            foreach ($widget->childNodes as $child) {   // each property is a child, so get the children
                if($child->nodeName == 'property') {    // filter out properties
                    $propertiesArr[$child->getAttribute('name')] = $child->nodeValue;    // save properties in the array
                }
                else if ($child->nodeName == 'child') { // otherwise handle more children
                    makeCallBasedOnElement($child);
                }
            }
            return $propertiesArr;                      // this is a simple parser, return just the properties
        }
    }

    // parses packing information to retrieve position of the widget
    function getWidgetPosition($packing) {              // former parsePacking
        $positionArr;
        foreach($packing->childNodes as $node) {
            if ($node->tagName == 'property') {
                // find out if this label is inside of another element (e.g. button)
                if ($node->getAttribute('name') == 'x') {
                    $positionArr['x']=$node->nodeValue;
                }
                else if ($node->getAttribute('name') == 'y') {
                    $positionArr['y']=$node->nodeValue;
                }
            }
        }
        return $positionArr;
    }

    // create a label
    function handleGtkLabel($label, $packing) {
        global $oneBigString;
    
        $labelClass = '';
        $labelPosition='display:inline;';
        
        // get label ID
        $labelID = getWidgetID($label);
        // get label's position
        $positionArr = getWidgetPosition($packing);
        
        if ($positionArr['x'] !== NULL) {
            $labelPosition = $labelPosition.'position:absolute; left:'.$positionArr['x'].'px;'.'top:'.$positionArr['y'].'px;';
            $labelClass = 'class="labelClass"';
        }
        
        // display:inline will make the label appear in the same line as the image
        $oneBigString=$oneBigString.'<div '.$labelClass.' id="'.$labelID.'Layer'.'" style="'.$labelPosition.'">
              <div style="display:inline; vertical-align: text-top;" id="'.$labelID.'">'."\n";
        $oneBigString=$oneBigString.getWidgetTitle($label)."\n";
        $oneBigString=$oneBigString.'</div>'."\n".'</div>'."\n";
    }
    
    // create a button with that particular button name
    function handleGtkButton($id, $packing) {
        global $oneBigString;
    
        // get buttonID
        $buttonID = getWidgetID($id);
        // get button's position
        $positionArr = getWidgetPosition($packing);
        
        $buttonStyle = 'position:absolute;white-space:nowrap;';
        
        if ($positionArr['x'] !== NULL) {
            $buttonStyle = $buttonStyle.'left:'.$positionArr['x'].'px;'.'top:'.$positionArr['y'].'px;';
        }
        // create HTML for the button
        $oneBigString=$oneBigString.'<button class="buttonClass" style="'.$buttonStyle.'" id="'.$buttonID.'" name="'.$buttonID.'Name'.'" type="button">';
        $propertiesArr = parseWidget($id);
        $oneBigString=$oneBigString.getWidgetTitle($id);
        $oneBigString=$oneBigString.'</button>';      // close the button tag
    }
    
    // this could be one of several types of input.  Create the appropriate HTML element based on exact type
    function handleGtkInput($id, $packing) {
        global $oneBigString;
    
        $textInputID = getWidgetID($id);
        
        $inputStyle = 'position:absolute;white-space:nowrap;';
        $inputType = 'radio';
        
        // get button's attributes and properties in an array
        $propertiesArr = parseWidget($id);
        // get button's packing info
        $positionArr = getWidgetPosition($packing);
        
        if ($positionArr['x'] !== NULL) {
            $inputStyle = $inputStyle.'left:'.$positionArr['x'].'px;'.'top:'.$positionArr['y'].'px;';
        }
        
        if ($id->getAttribute('class') == 'GtkCheckButton') {
            $inputType = 'checkbox';
        }
        else if ($id->getAttribute('class') == 'GtkRadioButton') {
            $textInputID = 'myRadio';               // to make sure that they are in the same group
        }
        
        if ($id->getAttribute('class') == 'GtkEntry') {
            $oneBigString=$oneBigString.'<input class="EntryClass" id="'.$textInputID.'" name="'.$textInputID.'" type="text" readonly="readonly" value="'.getWidgetTitle($id).'" style="'.$inputStyle.'"/>'."\n";
        }
        else {      // it is either radio or checkbox type                    
            $oneBigString=$oneBigString.'<div style="'.$inputStyle.'">'."\n";
            $oneBigString=$oneBigString.'<input id="'.$textInputID.'" name="'.$textInputID.'" type="'.$inputType.'" />';
            $oneBigString=$oneBigString.getWidgetTitle($id);
            $oneBigString=$oneBigString.'</div>'."\n";
        }
    }
    
    // for now we are handling only one level. There could be multiple levels of embedded layouts
    // we assume that there is no packing involved
    function handleGtkLayout($layout) {
        if ($layout->hasChildNodes()) {
            foreach($layout->childNodes as $child) {
                if ($child->tagName == 'child') {   // pick out just the <child> elements
                    makeCallBasedOnElement($child);
                }
            }
        }
    }
    
    // alignment does not have packing
    function handleGtkAlignment($alignment) {
        if($alignment->hasChildNodes()) {
            foreach ($alignment->childNodes as $child) {
                if ($child->tagName == 'child') {
                    makeCallBasedOnElement($child);
                }
            }
        }
    }
    
    // images are handled in a similar manner to the function in gladeToJS, note that we do not use <div> wrappers anywhere
    function handleGtkImage($image, $packing) {
        global $oneBigString;
        
        // get image ID
        $imageID = getWidgetID($image);
        
        $propertiesArr = parseWidget($image);
        // get image's position info
        $positionArr = getWidgetPosition($packing);
        
        $imageBufName = '';
        $imageLocation = 'gladeToJS/images/';
        $imageType = '';
        $imageStyle = '';
        
        if ($positionArr['x'] !== NULL) {
            $imageStyle = $imageStyle.'left:'.$positionArr['x'].'px;'.'top:'.$positionArr['y'].'px;';
            $imageStyle = $imageStyle.'position:absolute;';
        }
        // else it is inside a button, leave position to be default
        
        // figure out whether this icon is a stock icon or whether it is custom
        if(($propertiesArr['stock'] !== NULL) || ($propertiesArr['icon_name'] !== NULL)) {
            $imageLocation = $imageLocation.'stock/'.$propertiesArr['stock'];
            $imageType = '.png';
        }
        else if($propertiesArr['pixbuf'] !== NULL) {
            $imageLocation = $imageLocation.'other/'.$propertiesArr['pixbuf'];
        }
        
        if ($positionArr['x'] !== NULL) {
            $imageStyle = $imageStyle.'left:'.$positionArr['x'].'px;'.'top:'.$positionArr['y'].'px;';
        }
        else {          // else this is an inner image, display inline
            $imageStyle = $imageStyle.'display:inline;';
        }
        // display the image
        $oneBigString=$oneBigString.'<img src="'.$imageLocation.$imageType.'"  style="'.$imageStyle.'" id="'.$imageID.'" alt="myImage"/>';
    }
    
    function handleGtkComboBox($combo, $packing) {
        global $oneBigString;
    
        // get comboBox ID
        $comboID = getWidgetID($combo);
        
        $propertiesArr = parseWidget($combo);
        // get combo's packing info
        $positionArr = getWidgetPosition($packing);
        
        $comboLocation = $propertiesArr['items'];
        
        $comboStyle = 'position:absolute;width:30%;';
        
        if ($positionArr['x'] !== NULL) {
            $comboStyle = $comboStyle.'left:'.$positionArr['x'].'px;'.'top:'.$positionArr['y'].'px;';
        }

        // get the items of the combo box
        $tok = strtok($comboLocation, "\n");
        $oneBigString=$oneBigString.'<select style="'.$comboStyle.'" class="EntryClass" id="'.$comboID.'">'."\n";
        while ($tok !== false) {
            $oneBigString=$oneBigString.'<option value ="'.$tok.'">'.$tok.'</option>'."\n";
            $tok = strtok("\n");
        }
        $oneBigString=$oneBigString.'</select>'."\n";
    }
    
    // TODO: this function does not work for anything but GtkFixed Layout.  Extend to other layouts later!!
    function makeCallBasedOnElement($child) {
    	global $oneBigString;
        // packing is necessary to figure out widget location on the screen
        $packing = null;
        $childNodes = $child->childNodes;
        foreach ($child->childNodes as $someChild) {    // iterate over children of this node to find packing
            if($someChild->tagName == 'packing') {
                $packing = $someChild;
            }
        }
        foreach ($child->childNodes as $element) { // for every <child> tag get its children (named item)
            if (get_class($element) == 'DOMElement') {   // once again we get DOMText along with what we really want.  Filter DOMText out.
                if($element->getAttribute('class') != null) {   // precaution to make sure we have a valid element
                    $elementClass = $element->getAttribute('class');
                    if ($elementClass == 'GtkButton') {
                        handleGtkButton($element, $packing);
                    }
                    else if ($elementClass == 'GtkVBox') {
                        handleGtkLayout($element);
                    }
                    else if ($elementClass == 'GtkHBox') {
                        handleGtkLayout($element);
                    }
                    else if ($elementClass == 'GtkFixed') {
                        handleGtkLayout($element);
                    }
                    else if ($elementClass == 'GtkLabel') {
                        handleGtkLabel($element, $packing);
                    }
                    else if ($elementClass == 'GtkEntry') {
                        handleGtkInput($element, $packing);
                    }
                    else if ($elementClass == 'GtkCheckButton') {
                        handleGtkInput($element, $packing);
                    }
                    else if ($elementClass == 'GtkRadioButton') {
                        handleGtkInput($element, $packing);
                    }
                    else if ($elementClass == 'GtkImage') {
                        handleGtkImage($element, $packing);
                    }
                    else if ($elementClass == 'GtkAlignment') {
                        handleGtkAlignment($element);
                    }
                    else if ($elementClass == 'GtkComboBoxEntry') {
                        handleGtkComboBox($element, $packing);
                    }
                    else $oneBigString=$oneBigString.'<br /> UNKNOWN tag '.$element->tagName.'<br />';
                }
            }
        }
    }
    
    function displayGtkWindow($window) {
    global $totalX;
    global $totalY;
    global $oneBigString;
    
    //<link rel="stylesheet" title="Flower (Default)" href="css/gladeMainCSS.css" type="text/css" media="screen"/>
    
    // the HTML below emulates WalterZorn's implementation.  This took a bit of time to tweak to the right values.
    // if you need to change them, play around with positions of resizehandle and resizebutton images first.
    
    $oneBigString=$oneBigString.
    '<div>
        <link rel="stylesheet" title="Flower (Default)" href="gladeToJS/css/gladeMainCSS.css" type="text/css" media="screen"/>
        <div id="titlebar" style="position:relative;border:none;background:#4455aa;overflow:hidden; z-index:1000; width:'.($totalX+20).'px;height:16px;">
            <span style="position:relative;left:2px;top:2px;bottom:2px;color:white;font-weight:bold;font-size:11px;font-family:Verdana,Geneva,sans-serif;">
                &nbsp;'.getWidgetTitle($window).
            '</span>
        </div>';
        $oneBigString=$oneBigString.
        '<div id="frame" style="width:'.($totalX+20).'px;height:'.($totalY+5).'px;background:#cccccc;">
            <div id="clientarea" style="position:relative;border:2px inset #cccccc;overflow:auto; width:'.($totalX+10).'px; height:'.($totalY-38).'px; left:3px; top:19px;">';

                foreach ($window->childNodes as $item) {    // scan through the list of childNodes of a window.  The list includes all window properties.
                    if (get_class($item) == 'DOMElement') { // we get DOMText mixed in as well.  Filter that out.
                        if ($item->tagName == 'child') {    // find ONLY children. We don't care about window properties for now
                            makeCallBasedOnElement($item);  // we can just have buttons here, not necessarily layouts, so handle it
                        }
                    }
                }
                
    $oneBigString=$oneBigString.
            '</div>
        </div>
        <img name="resizehandle" style="position:relative; z-index:500; left:'.$totalX.'px; top:-20px;" src="gladeToJS/winresize.gif" width="20" height="20" alt="" />
    </div>
    <img name="resizebutton" style="position:relative; z-index:1500; left:'.($totalX+4).'px; top:-'.($totalY+40).'px;" src="gladeToJS/button_up_outset.gif" width="16" height="14" alt="" />';
    }
    
    
    /**
     * Hold thrown errors statically
     */
    function staticerror($errno, $errstr, $errfile, $errline, $errcontext, $ret = false) {
       static $errs = array();
    
       if ($ret === true) {
           return $errs;
       }
    
       $tag = 'DOMDocument::validate(): ';
       $errs[] = str_replace($tag, '', $errstr);
    }
    
    
    // Main Document Processing
    function mainDocProcess($file) {
        global $totalX;
        global $totalY;
        global $maxX;
        global $maxY;
        global $widthRequest;
        global $heightRequest;
        global $largestPackingNode;
        global $oneBigString;
        
        
        
        // Load a document
        $doc = DOMDocument::loadXML($file);
        
        
        // -- dreamhost implementation to validate the schema -- //
        // Set up error handling
        set_error_handler('staticerror');
        $old = ini_set('html_errors', false);
        
        // Validate
        if ($doc->validate()) {
            // $oneBigString = $oneBigString.'validation passed';
            //$oneBigString = $oneBigString.'actualEncoding: '.$doc->actualEncoding.'  '.'doctype name: '.$doc->doctype->name.'  '.
            //            'doctype publicId: '.$doc->doctype->publicId.'  '.'xmlEncoding: '.$doc->xmlEncoding.'  ';
        }
        //else $oneBigString=$oneBigString."NOT VALID \n";
        $doc->validateOnParse = true;
        
        // Restore error handling
        ini_set('html_errors', $old);
        restore_error_handler();
        // -- end dreamhost implementation to validate the schema -- //
        
        
        // find the totalX and totalY positions
        $packingNodes = $doc->getElementsByTagName('packing');
        $tempX;
        $tempY;
        foreach($packingNodes as $pChild) {                                                 // examine every packing node
            foreach ($pChild->getElementsByTagName('property') as $pName) {
                if ($pName->getAttribute('name') == 'x') {                                  // extract x
                    $tempX = $pName->nodeValue;
                }
                else if ($pName->getAttribute('name') == 'y') {                             // extract y
                    $tempY = $pName->nodeValue;
                }
            }
            foreach($pChild->previousSibling->previousSibling->childNodes as $widgetProp) {
                if($widgetProp->nodeName == 'property') {
                    if($widgetProp->getAttribute('name') == 'width_request') {          // extract width
                        $tempX = $tempX + $widgetProp->nodeValue;
                    }
                    else if($widgetProp->getAttribute('name') == 'height_request') {    // extract height
                        $tempY = $tempY + $widgetProp->nodeValue;
                    }
               }
            }
                
            if (($tempX <= $maxX) && ($tempX > $totalX)) {          // set new x value
                $totalX = $tempX;
            }
            if (($tempY <= $maxY) && ($tempY > $totalY)) {          // set new y value
                $totalY = $tempY;
            }
        }
        // change totalY to reflect title bar, padding etc.
        $totalY = $totalY+45;
        // render elements
        $nodeList = $doc->getElementsByTagName('widget');
        
        // execute first parsing step
        foreach ($nodeList as $param) {
            if ($param->getAttribute('class') == 'GtkWindow') { // Render windows first
                displayGtkWindow($param);
            }
        }
    }
?>
Return current item: ColGUI