The final program
<?php
if( !extension_loaded('gtk')) {	
    dl( 'php_gtk.' . PHP_SHLIB_SUFFIX);
}

$fdnd = new FileDragNDrop();
$fdnd->buildDialog();
$fdnd->display();

class FileDragNDrop
{
    function buildDialog() {
        $this->window =& new GtkWindow();
        $this->window->set_title('FileDropper');
        $this->window->set_default_size(200, 200);
        $this->window->connect_object('destroy', array('gtk', 'main_quit'));
       
        $scrolledwindow =& new GtkScrolledWindow();
        $scrolledwindow->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
        $this->window->add($scrolledwindow); 
        
        $this->tree =& new GtkCTree(3, 0, array('title', 'url', 'local path'));
        $scrolledwindow->add($this->tree);
        
        $this->ndToplevel = $this->tree->insert_node(null, null, array('Files', '', ''), 0, null, null, null, null, false, true);
        
        $this->tree->connect('key-press-event', array(&$this, 'keyPressedTree'));
        $this->tree->connect( 'drag-data-received', array( &$this, 'dragDataReceived'));
        
        $this->targets = array( array( 'text/uri-list', 0, 0));
        $this->tree->drag_dest_set( GTK_DEST_DEFAULT_ALL, $this->targets, GDK_ACTION_COPY | GDK_ACTION_MOVE);

        $this->tree->drag_source_set(GDK_BUTTON1_MASK, $this->targets, GDK_ACTION_COPY);
        $this->tree->connect('drag-data-get', array(&$this, 'dragDataGet'));
    }
    
    
    function display() {
        $this->window->show_all();
        gtk::main();
    }
    
    function keyPressedTree($tree, $objEvent) {
        if ($objEvent->keyval == GDK_KEY_Delete) {
            $ar =  $tree->selection;
            foreach ($ar as $objNode) {
                $tree->remove_node($objNode);
            }
        }
    }
        
    function dragDataReceived($tree, $context , $x, $y, $data , $info, $time) {
        if (count($tree->selection) != 1) {
            $parent = $this->ndToplevel;
        } else {
            $parent = $tree->selection[0];
        }
    
        $strData    = $data->data;
        $arData     = explode("\n", $strData);
        foreach ($arData as $strLine) {
            $strFile    = trim($strLine);
            if ($strFile == '') { continue; }
            $tree->insert_node($parent, null, array(basename(urldecode($strFile)), $strFile, $this->getPathFromUrilistEntry($strFile)), 0, null, null, null, null, false, true);
        }
        $tree->columns_autosize();
    }
        
    /**
    *   converts a file path gotten from a text/uri-list
    *   drop to a usable local filepath
    *   @param  string  The line from the uri-list
    *   @return string  The usable local filepath
    */
    function getPathFromUrilistEntry($strUriFile)
    {
        $strUriFile = urldecode($strUriFile);//should be URL-encoded
        $bUrl = false;
        if (substr($strUriFile, 0, 5) == 'file:')
        {   //(maybe buggy) file protocol
            if (substr($strUriFile, 0, 17) == 'file://localhost/') {
                //correct implementation
                $strFile = substr($strUriFile, 16);
            } else if (substr($strUriFile, 0, 8) == 'file:///') {
                //no hostname, but three slashes - nearly correct
                $strFile = substr($strUriFile, 7);
            } else if ($strUriFile[5] == '/') {
                //theoretically, the hostname should be the first
                //but no one implements it
                $strUriFile = substr($strUriFile, 5);
                for( $n = 1; $n < 5; $n++) {
                    if ($strUriFile[$n] != '/') { break; }
                }
                $strUriFile = substr($strUriFile, $n - 1);
                if (!file_exists($strUriFile)) {
                    //perhaps a correct implementation with hostname???
                    $strUriFileNoHost = strstr(substr($strUriFile, 1), '/');
                    if (file_exists($strUriFileNoHost)) {
                        //seems so
                        $strUriFile = $strUriFileNoHost;
                    }
                }
                $strFile = $strUriFile;
            } else {
                //NO slash after "file:" - what is that for a crappy program?
                $strFile = substr ($strUriFile, 5);
            }
        } else if (strstr($strUriFile, '://')) {
            //real protocol, but not file
            $strFile = $strUriFile;
            $bUrl    = true;
        } else {
            //local file?
            $strFile = $strUriFile;
        }
        if (!$bUrl && $strFile[2] == ':' && $strFile[0] == '/') {
            //windows file path
            $strFile = str_replace('/', '\\', substr($strFile, 1));
        }
        return $strFile;
    }
    
    function dragDataGet($tree, $context, $selection_data, $info, $time) {
        if( count( $tree->selection) < 1) { return false; }
        $node = $tree->selection[0];
        $file = $tree->node_get_text( $node, 2);
        if( $file == '') { return false; }
        $selection_data->set($selection_data->target, 8, $this->pathurlencode($this->getUriFromFile($file)) . "\r\n");
    }
        
    /**
    *   converts a file name to a URI
    *   useful to convert a file to the text/uri-list compatible format
    *   @param  string  The file
    *   @return string  The URI
    */
    function getUriFromFile($strFile) {
        if (strstr($strFile, '://')) {
            //real URL
            $strUri = $strFile;
        } else {
            //normal file
            if (substr($strFile, 1, 2) ==  ':\\') {
                //windows path c:\programs\bla\blu\file.bli
                $strUri = 'file://localhost/' . str_replace('\\', '/', $strFile);
            } else {
                //should be nice unix file
                //@fixme: convert relative names to absolute ones?
                $strUri = 'file://localhost' . realpath($strFile);
            }
        }
        return $strUri;
    }
    
    
    function pathurlencode($uri) {
        $uri = urlencode($uri);
        $uri = str_replace('%3A', ':', $uri);
        $uri = str_replace('%2F', '/', $uri);
        $uri = str_replace('%26', '&', $uri);
        $uri = str_replace('%40', '@', $uri);
        $uri = str_replace('%3A', ':', $uri);
        $uri = str_replace('%3F', '?', $uri);
        return $uri;
    }
}
?>
© Copyright 2003-2023 www.php-editors.com. The ultimate PHP Editor and PHP IDE site.