読者です 読者をやめる 読者になる 読者になる

1週間でFlexファイラを作ろうプロジェクト 3日目

昨日に引き続き、3日目。

  • ファイラウィンドウを別のmxmlファイルに分けた
  • ウィンドウを複数作れるようなった
  • ウィンドウがD&Dで移動できるようになった(ちょっと挙動不審)
  • ウィンドウがドラッグしてリサイズできるようになった(もうちょっと挙動不審)

今日の成果はこのあたり (ソースコード)にあります。

今日の変更はクライアント側(Flex側)だけです。

  • FlexFile.mxml
<?xml version="1.0" encoding="utf-8"?>                                                                                                
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:ff="*" creationComplete="init()" layout="horizontal">                 
        <mx:Script>
                <![CDATA[                                                                                                             
                public function addNewWindow(event:MouseEvent):void                                                                   
                {
                        var ffw:FlexFileWindow = new FlexFileWindow();                                                                
                        ffw.width  = canvas.width/2;                                                                                  
                        ffw.height = canvas.height/2;                                                                                 
                        ffw.x = (canvas.width  - ffw.width) / 2;                                                                      
                        ffw.y = (canvas.height - ffw.height) / 2;                                                                     
                        canvas.addChild(ffw);                                                                                         
                }
                ]]>
        </mx:Script>
        <mx:VBox height="100%">                                                                                                       
                <mx:Button label="add" click="addNewWindow(event)"/>                                                                  
        </mx:VBox>                                                                                                                    
        
        <mx:Canvas width="100%" height="100%" id="canvas">                                                                            
                <!--<ff:FlexFileWindow/>-->                                                                                           
                <ff:FlexFileWindow width="60%" height="60%"/>                                                                         
        </mx:Canvas>                                                                                                                  
</mx:Application>
  • FlexFileWindow.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml">

        <mx:Panel width="100%" height="100%" creationComplete="init()" id="panel">

                <mx:Script source="FlexFileWindow.as"/>

                <mx:DataGrid id="grid" width="100%" height="100%" doubleClickEnabled="true" doubleClick="onDoubleClickData(event)">
                        <mx:columns>
                                <mx:DataGridColumn dataField="name" headerText="name" width="200"/>
                                <mx:DataGridColumn dataField="size" headerText="size" width="100" textAlign="right" sortCompareFunction="sizeSortCompareFunction"/>
                                <mx:DataGridColumn dataField="type" headerText="type" width="100" textAlign="right"/>
                        </mx:columns>
                </mx:DataGrid>

                <mx:ControlBar>
                        <mx:VBox width="100%">
                                <mx:HBox width="100%">
                                        <mx:Label id="pathInput" width="100%"/>
                                        <!--<mx:TextInput id="pathInput" width="100%"/>-->
                                        <mx:Button label="Upload" click="onUpload(event)"/>
                                </mx:HBox>
                                <mx:TextArea width="100%" height="40" id="area"/>
                        </mx:VBox>
                </mx:ControlBar>                                                                                                      



        </mx:Panel>

        <mx:HTTPService id="fileService"
                showBusyCursor="true"
                result="onResult(event)"
                fault="onFault(event)" />

        <mx:VBox backgroundColor="#eeee00" width="15" height="15" y="{height-15}" x="{width-15}" id="resizer"/>

</mx:Canvas>
  • FlexFileWindow.as
// vim:syntax=javascript

import mx.controls.Alert;
import mx.rpc.events.*;
import mx.rpc.http.HTTPService;
import mx.utils.ObjectUtil;
import flash.net.FileReference;
import mx.collections.ArrayCollection;
import mx.utils.StringUtil;

private var _resizing:Boolean;
private var _serverURL:String;
private var _currentPath:String;
private var _uploadFile:FileReference;
private var _downloadFile:FileReference;

public function set title(str:String):void
{
        panel.title = str;
}

private function init():void
{
        _serverURL = "http://syuki.skr.jp/test/flex/flexfile_03.cgi";

        fileService.url = _serverURL;
        this.title = _serverURL.replace(/^.+\:\/\//, "flexfile\:\/\/");

        sendRequest("/");

        _uploadFile = new FileReference();
        _uploadFile.addEventListener(Event.SELECT, uploadFileSelected);
        _uploadFile.addEventListener(Event.COMPLETE, uploadFileComplete);
        _uploadFile.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, uploadFileCompleteAndResponse);
        _uploadFile.addEventListener(IOErrorEvent.IO_ERROR, uploadIOError);
        _uploadFile.addEventListener(SecurityErrorEvent.SECURITY_ERROR, uploadSecurityError);

        _downloadFile = new FileReference();
        _downloadFile.addEventListener(Event.SELECT, downloadFileSelected);
        _downloadFile.addEventListener(Event.COMPLETE, downloadFileComplete);
        _downloadFile.addEventListener(IOErrorEvent.IO_ERROR, downloadIOError);
        _downloadFile.addEventListener(SecurityErrorEvent.SECURITY_ERROR, downloadSecurityError);


        addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
        addEventListener(MouseEvent.MOUSE_UP, mouseReleased);
        //this.titleBar.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
        //this.titleBar.addEventListener(MouseEvent.MOUSE_UP, mouseReleased);

        _resizing = false;
        resizer.addEventListener(MouseEvent.MOUSE_DOWN, startResize);
        this.addEventListener(MouseEvent.MOUSE_MOVE, doResize);
        resizer.addEventListener(MouseEvent.MOUSE_UP, stopResize);
}
private function mouseDown(event:MouseEvent):void {
        this.startDrag();
        parent.setChildIndex(this, parent.numChildren - 1);
}
private function mouseReleased(event:MouseEvent):void {
        stopDrag();
}

private function startResize(event:MouseEvent):void
{
        resizer.startDrag();
        event.stopPropagation();
        _resizing = true;
}
private function doResize(event:MouseEvent):void
{       
        if(_resizing) {
                this.width  = resizer.x+15;
                this.height = resizer.y+15;
        }
}
private function stopResize(event:MouseEvent):void
{       
        _resizing = false;
        stopDrag(); 
        resizer.x = this.width - 15;
        resizer.y = this.height - 15;
}


private function sendRequest(path:String):void
{       
        fileService.method = "GET"; 
        fileService.request.command = "list";
        fileService.request.path = path;
        fileService.send();
}

private function refreshFileList(entries:Object):void
{       
        grid.dataProvider = entries;
}

private function onResult(e:ResultEvent):void
{       
        refreshFileList(fileService.lastResult.DirectoryEntryList.DirectoryEntries.entry);
        _currentPath = fileService.lastResult.DirectoryEntryList.path;
        pathInput.text = _currentPath;
}

private function onFault(e:FaultEvent):void
{       
        Alert.show(e.fault.faultString);
}

private function sizeSortCompareFunction(obj1:Object, obj2:Object):int
{       
        var num1:Number = obj1.size;
        var num2:Number = obj2.size;
        if( isNaN(num1) && isNaN(num2) ) {
                return 0;
        } else if(  isNaN(num1) && !isNaN(num2) ) {
                return 1;
        } else if( !isNaN(num1) &&  isNaN(num2) ) {
                return -1;
        } else if( num1 < num2 ) {
                return 1; 
        } else if( num1 > num2 ) {
                return -1;
        }
        return 0;
}

private function onDoubleClickData(event:MouseEvent):void
{       
        var item:Object = event.currentTarget.selectedItem;
        if( item.type == "directory" ) {
                
                area.text = "list: " + _currentPath + "/" + item.name;
                sendRequest( _currentPath + "/" + item.name );
        
        } else {
                
                area.text = "download: " + _currentPath + "/" + item.name;
                
                var req:URLRequest = new URLRequest(fileService.url);
                req.method = URLRequestMethod.GET;
                var cmd:URLVariables = new URLVariables();
                cmd.command = "download"; 
                cmd.path = _currentPath + "/" + item.name;
                req.data = cmd;
                _downloadFile.download(req, item.name);
        
        }
}

private function onUpload(event:MouseEvent):void
{       
        _uploadFile.browse();
}

private function uploadFileSelected(event:Event):void
{       
        var file:FileReference = FileReference(event.target);
        var req:URLRequest = new URLRequest(fileService.url);
        req.method = URLRequestMethod.GET;
        var cmd:URLVariables = new URLVariables();
        cmd.command = "upload";
        cmd.path = _currentPath;
        req.data = cmd;
        file.upload(req, "file");
}

private function uploadFileComplete(event:Event):void
{
}

private function uploadIOError(event:IOErrorEvent):void
{       
        Alert.show("Upload failed: " + event.target.name + ":\n" + event.text );
}

private function uploadSecurityError(event:SecurityErrorEvent):void
{
        Alert.show("Upload failed: " + event.target.name + ":\n" + event.text );
}


private function uploadFileCompleteAndResponse(event:DataEvent):void
{       
        var xml:XML = XML(event.text.toString());
        if( xml.name().localName == "QueryError" ) {
                Alert.show("Upload failed: " + event.target.name + ":\n" + xml.Message );
        } else {
                Alert.show(event.target.name + " is successfully uploaded.");
                refreshFileList(xml.DirectoryEntries.entry);
        }
}


private function downloadFileSelected(event:Event):void
{
}

private function downloadFileComplete(event:Event):void
{       
        //Alert.show(event.target.name + " is successfully downloaded.");
}

private function downloadIOError(event:IOErrorEvent):void
{       
        Alert.show("Download failed: " + event.target.name + ":\n" + event.text );
}

private function downloadSecurityError(event:SecurityErrorEvent):void
{       
        Alert.show("Download failed: " + event.target.name + ":\n" + event.text );
}

ポイントは、startDrag()とstopDrag()。なんともお手軽なことに、ドラッグしたいインスタンスにstartDrag()を呼ぶだけでドラッグしてくれます。

resizer(右下の黄色い四角)は、ドラッグされているときにマウスイベント(MouseEvent.MOUSE_MOVE)を捕捉して、親のCanvasの大きさを変えています。これでドラッグしてリサイズを実現。
ただ、急激にウィンドウを大きくすると、親のCanvasにスクロールバーが出てしまって、大きさが変わらなくなってしまうという問題が。うーむ。どうしたものか…