- merge deskshare from branch into trunk

git-svn-id: http://bigbluebutton.googlecode.com/svn/trunk@1767 af16638f-c34d-0410-8cfa-b39d5352b314
This commit is contained in:
Richard Alam 2009-06-23 18:00:30 +00:00
parent 4bc66fdb61
commit cdbe88f2a0
23 changed files with 1952 additions and 102 deletions

View File

@ -43,6 +43,7 @@
<module application="src/BigBlueButton.mxml" destPath="JoinModule.swf" optimize="true" sourcePath="src/JoinModule.mxml"/>
<module application="src/BigBlueButton.mxml" destPath="PhoneModule.swf" optimize="true" sourcePath="src/PhoneModule.mxml"/>
<module application="src/BigBlueButton.mxml" destPath="Red5PhoneModule.swf" optimize="true" sourcePath="src/Red5PhoneModule.mxml"/>
<module application="src/BigBlueButton.mxml" destPath="DeskShareModule.swf" optimize="true" sourcePath="src/DeskShareModule.mxml"/>
</modules>
<buildCSSFiles/>
</actionScriptProperties>

Binary file not shown.

View File

@ -85,6 +85,42 @@ if ( hasProductInstall && !hasRequestedVersion ) {
document.write(alternateContent); // insert non-flash content
}
// -->
function startApplet(IP, roomNumber, captureX, captureY, captureWidth, captureHeight)
{
var iframe = document.createElement("iframe");
iframe.id = "iframe";
document.body.appendChild(iframe);
frames[frames.length - 1].document.write("<applet id="+ "\"DeskShareApplet\" " + "NAME=" + "\"DeskShareApplet\" " +
"height=" + "\"0\" " +"width="+ "\"0\" " +"scriptable="+ "\"true\" " +
"mayscript=" + "\"true\">" +
"<param name=" +"\"CODE\" "+ "value=" + "\"test.RunnerApplet.class\"" + "></param>"+
"<param name=" +"\"ROOM\" "+ "value=" + "\"" + roomNumber + "\"" + "></param>"+
"<param name=" +"\"IP\" " + "value=" + "\"" + IP + "\"" + "></param>"+
"<param name=" +"\"CAPTURE_WIDTH\" " + "value=" + "\"" + captureWidth + "\"" + "></param>"+
"<param name=" +"\"CAPTURE_HEIGHT\" " + "value=" + "\"" + captureHeight + "\"" + "></param>"+
"<param name=" +"\"X\" " + "value=" + "\"" + captureX + "\"" + "></param>"+
"<param name=" +"\"Y\" " + "value=" + "\"" + captureY + "\"" + "></param>"+
"<param name=" +"\"ARCHIVE\" " + "value="+ "\"deskShare.jar\"" + "></param> </applet>");
}
function removeFrame () {
var iframe = document.getElementById("iframe");
iframe.parentNode.removeChild(iframe);
}
function setScreenCoordinates(x, y) {
return frames[frames.length - 1].document.DeskShareApplet.setScreenCoordinates(x,y);
}
function stopApplet(){
frames[frames.length - 1].document.DeskShareApplet.destroy();
}
function checkForJava(){
if (navigator.javaEnabled()) return 1;
}
</script>
<noscript>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"
implements="org.bigbluebutton.common.IBigBlueButtonModule"
creationComplete="onCreationComplete()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import org.bigbluebutton.modules.deskShare.DeskShareFacade;
import org.bigbluebutton.modules.chat.ChatFacade;
import org.bigbluebutton.common.messaging.Router;
private var _router:Router;
private var _moduleId:String = "DeskShareModule";
private var _moduleName:String = "Desk Share";
private var _attributes:Object;
private function onCreationComplete():void{
LogUtil.debug("DeskShareModule initialized");
}
public function acceptRouter(router:Router):void{
_router = router;
}
public function get router():Router{
return _router;
}
public function get moduleId():String{
return _moduleId;
}
public function get moduleName():String{
return _moduleName;
}
public function get uri():String{
if (_attributes.mode == "PLAYBACK")
return _attributes.uri + "/" + _attributes.playbackRoom;
return _attributes.uri + "/" + _attributes.room;
}
public function get username():String{
return _attributes.username;
}
public function get connection():NetConnection{
return _attributes.connection;
}
public function get mode():String{
if (_attributes.mode == null){
_attributes.mode = "LIVE";
LogUtil.debug("Setting DeskShare mode: " + _attributes.mode);
}
LogUtil.debug("DeskShare mode: " + _attributes.mode);
return _attributes.mode;
}
public function get userid():Number{
return _attributes.userid as Number;
}
public function get role():String{
return _attributes.userrole as String;
}
public function start(attributes:Object):void{
LogUtil.debug("chat attr: " + attributes.username);
_attributes = attributes;
DeskShareFacade.getInstance().startup(this);
}
public function stop():void{
DeskShareFacade.getInstance().stop(this);
}
public function getRoom():String{
return _attributes.room;
}
public function getRed5ServerUri():String{
return _attributes.uri;
}
public function getCaptureServerUri():String{
var uri:String = _attributes.uri;
uri = uri.split("/")[2];
//Alert.show(uri);
return uri;
}
]]>
</mx:Script>
</mx:Module>

View File

@ -1,39 +1,47 @@
<?xml version="1.0" ?>
<config>
<version>0.4</version>
<porttest host="192.168.0.103" application="oflaDemo"/>
<modules>
<module name="VideoModule" url="VideoModule.swf"
uri="rtmp://192.168.0.103/oflaDemo"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="ChatModule" url="ChatModule.swf"
uri="rtmp://192.168.0.103/bigbluebutton"
loadNextModule="PresentationModule"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="ViewersModule" url="ViewersModule.swf"
uri="rtmp://192.168.0.103/bigbluebutton"
host="http://192.168.0.103/bigbluebutton/conference-session/enter"
onAppInitEvent="LOAD" loadNextModule="ChatModule"
onAppStartEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="ListenersModule" url="ListenersModule.swf"
uri="rtmp://192.168.0.103/bigbluebutton"
recordingHost="http://192.168.0.103"
loadNextModule="VideoModule"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="PresentationModule" url="PresentationModule.swf"
uri="rtmp://192.168.0.103/bigbluebutton"
host="http://192.168.0.103"
loadNextModule="ListenersModule"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
</modules>
</config>
<?xml version="1.0" ?>
<config>
<version>0.4</version>
<porttest host="192.168.0.172" application="oflaDemo"/>
<modules>
<module name="VideoModule" url="VideoModule.swf"
uri="rtmp://192.168.0.172/oflaDemo"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
loadNextModule="DeskShareModule"
/>
<module name="ChatModule" url="ChatModule.swf"
uri="rtmp://192.168.0.172/bigbluebutton"
loadNextModule="PresentationModule"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="ViewersModule" url="ViewersModule.swf"
uri="rtmp://192.168.0.172/bigbluebutton"
host="conf/join-mock.xml"
onAppInitEvent="LOAD" loadNextModule="ChatModule"
onAppStartEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="ListenersModule" url="ListenersModule.swf"
uri="rtmp://192.168.0.172/bigbluebutton"
recordingHost="http://192.168.0.172"
loadNextModule="VideoModule"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="PresentationModule" url="PresentationModule.swf"
uri="rtmp://192.168.0.172/bigbluebutton"
host="http://192.168.0.172"
loadNextModule="ListenersModule"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="DeskShareModule" url="DeskShareModule.swf"
uri="rtmp://192.168.0.172/deskShare"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
</modules>
</config>

View File

@ -1,10 +1,10 @@
<join>
<returncode>SUCCESS</returncode>
<fullname>Richard</fullname>
<role>MODERATOR</role>
<conference>11e59b6d-fe0a-4ca5-8be4-c07b85d3eff8</conference>
<room>c87bead2-d230-4887-aba2-3418fb60e5dc</room>
<voicebridge>85115</voicebridge>
<record>true</record>
<mode>LIVE</mode>
<join>
<returncode>SUCCESS</returncode>
<fullname>Richard</fullname>
<role>MODERATOR</role>
<conference>965e0dcb-f64c-49bd-a81c-2e7e721fa147</conference>
<room>f7e8821f-8528-4c28-994e-2db7659f9538</room>
<voicebridge>85005</voicebridge>
<mode>LIVE</mode>
<record>true</record>
</join>

View File

@ -1,55 +1,55 @@
<modules version="0.4a">
<!--module name="LoginModule" url="LoginModule.swf"
uri="http://localhost:8080/bigbluebutton/join/signIn"
onAppInitEvent="LOAD" loadNextModule="ChatModule"
onAppStartEvent="START"
onUserLogoutEvent="STOP"
uri="http://localhost:8080/bigbluebutton/conference-session/enter"
/-->
<!--
<module name="JoinModule" url="JoinModule.swf"
uri="conf/join-mock.xml"
onAppInitEvent="LOAD"
onAppStartEvent="START"
onUserLogoutEvent="STOP"
/>
host="http://localhost:8080/bigbluebutton/conference-session/enter"
-->
<module name="VideoModule" url="VideoModule.swf"
uri="rtmp://192.168.0.103/oflaDemo"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="ChatModule" url="ChatModule.swf"
uri="rtmp://192.168.0.103/bigbluebutton"
loadNextModule="PresentationModule"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="ViewersModule" url="ViewersModule.swf"
uri="rtmp://192.168.0.103/bigbluebutton"
host="conf/join-mock.xml"
onAppInitEvent="LOAD" loadNextModule="ChatModule"
onAppStartEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="ListenersModule" url="ListenersModule.swf"
uri="rtmp://192.168.0.103/bigbluebutton"
recordingHost="http://localhost"
loadNextModule="VideoModule"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="PresentationModule" url="PresentationModule.swf"
uri="rtmp://192.168.0.103/bigbluebutton"
host="http://192.168.0.103"
loadNextModule="ListenersModule"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
<modules version="0.4a">
<!--module name="LoginModule" url="LoginModule.swf"
uri="http://localhost:8080/bigbluebutton/join/signIn"
onAppInitEvent="LOAD" loadNextModule="ChatModule"
onAppStartEvent="START"
onUserLogoutEvent="STOP"
uri="http://localhost:8080/bigbluebutton/conference-session/enter"
/-->
<!--
<module name="JoinModule" url="JoinModule.swf"
uri="conf/join-mock.xml"
onAppInitEvent="LOAD"
onAppStartEvent="START"
onUserLogoutEvent="STOP"
/>
host="http://localhost:8080/bigbluebutton/conference-session/enter"
-->
<module name="VideoModule" url="VideoModule.swf"
uri="rtmp://localhost/oflaDemo"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="ChatModule" url="ChatModule.swf"
uri="rtmp://localhost/bigbluebutton"
loadNextModule="PresentationModule"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="ViewersModule" url="ViewersModule.swf"
uri="rtmp://localhost/bigbluebutton"
host="conf/join-mock.xml"
onAppInitEvent="LOAD" loadNextModule="ChatModule"
onAppStartEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="ListenersModule" url="ListenersModule.swf"
uri="rtmp://localhost/bigbluebutton"
recordingHost="http://localhost"
loadNextModule="VideoModule"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
<module name="PresentationModule" url="PresentationModule.swf"
uri="rtmp://localhost/bigbluebutton"
host="http://localhost:8080"
loadNextModule="ListenersModule"
onUserJoinedEvent="START"
onUserLogoutEvent="STOP"
/>
</modules>

View File

@ -0,0 +1,121 @@
package org.bigbluebutton.modules.deskShare
{
import org.bigbluebutton.common.IBigBlueButtonModule;
import org.bigbluebutton.common.messaging.Endpoint;
import org.bigbluebutton.common.messaging.EndpointMessageConstants;
import org.bigbluebutton.common.messaging.Router;
import org.puremvc.as3.multicore.interfaces.IMediator;
import org.puremvc.as3.multicore.interfaces.INotification;
import org.puremvc.as3.multicore.patterns.mediator.Mediator;
import org.puremvc.as3.multicore.utilities.pipes.interfaces.IPipeMessage;
/**
* This is the EndpointMediator for the DeskShareModule
* @author Snap
*
*/
public class DeskShareEndpointMediator extends Mediator implements IMediator
{
public static const NAME:String = "DeskShareEndpointMediator";
private var _module:IBigBlueButtonModule;
private var _router:Router;
private var _endpoint:Endpoint;
private static const TO_DESK_SHARE_MODULE:String = "TO_DESK_SHARE_MODULE";
private static const FROM_DESK_SHARE_MODULE:String = "FROM_DESK_SHARE_MODULE";
private static const PLAYBACK_MESSAGE:String = "PLAYBACK_MESSAGE";
private static const PLAYBACK_MODE:String = "PLAYBACK_MODE";
/**
* The constructor
* @param module - The DeskShareModule which this class is serving as EndpointMediator for
*
*/
public function DeskShareEndpointMediator(module:IBigBlueButtonModule)
{
super(NAME, module);
_module = module;
_router = module.router;
LogUtil.debug("creating endpoint for DeskShare module");
_endpoint = new Endpoint(_router, FROM_DESK_SHARE_MODULE, TO_DESK_SHARE_MODULE, messageReceiver);
}
override public function getMediatorName():String{
return NAME;
}
/**
* Lists the notifications to which this class listens to
* @return
*
*/
override public function listNotificationInterests():Array{
return [
DeskShareModuleConstants.ADD_WINDOW,
DeskShareModuleConstants.REMOVE_WINDOW,
DeskShareModuleConstants.CONNECTED,
DeskShareModuleConstants.DISCONNECTED
];
}
/**
* Handles relevant notifications as they are received
* @param notification
*
*/
override public function handleNotification(notification:INotification):void{
LogUtil.debug("DeskShareEndpoint MSG. " + notification.getName());
switch(notification.getName()){
case DeskShareModuleConstants.ADD_WINDOW:
LogUtil.debug("sending DeskShare OPEN_WINDOW message to main");
_endpoint.sendMessage(EndpointMessageConstants.ADD_WINDOW, EndpointMessageConstants.TO_MAIN_APP, notification.getBody());
break;
case DeskShareModuleConstants.REMOVE_WINDOW:
LogUtil.debug("sending DeskShare CLOSE_WINDOW message to main");
_endpoint.sendMessage(EndpointMessageConstants.REMOVE_WINDOW, EndpointMessageConstants.TO_MAIN_APP, notification.getBody());
break;
case DeskShareModuleConstants.CONNECTED:
LogUtil.debug("sending DeskShare MODULE_STARTED message to main");
_endpoint.sendMessage(EndpointMessageConstants.MODULE_STARTED, EndpointMessageConstants.TO_MAIN_APP, _module.moduleId);
facade.sendNotification(DeskShareModuleConstants.OPEN_WINDOW);
break;
case DeskShareModuleConstants.DISCONNECTED:
LogUtil.debug("sending DeskShare MODULE_STOPPER message to main");
facade.sendNotification(DeskShareModuleConstants.CLOSE_WINDOW);
var info:Object = new Object();
info["moduleId"] = _module.moduleId;
_endpoint.sendMessage(EndpointMessageConstants.MODULE_STOPPED, EndpointMessageConstants.TO_MAIN_APP, info);
break;
}
}
/**
* Called when a message is received from somewhere outside the DeskShareModule
* @param message
*
*/
private function messageReceiver(message:IPipeMessage):void{
var msg:String = message.getHeader().MSG as String;
switch(msg){
case EndpointMessageConstants.OPEN_WINDOW:
break;
case EndpointMessageConstants.CLOSE_WINDOW:
facade.sendNotification(DeskShareModuleConstants.CLOSE_WINDOW);
break;
}
}
/**
* A method for playing back messages in Playback Mode
* @not implemented
* @param message
*
*/
private function playMessage(message:XML):void{
}
}
}

View File

@ -0,0 +1,65 @@
package org.bigbluebutton.modules.deskShare
{
import org.bigbluebutton.common.IBigBlueButtonModule;
import org.bigbluebutton.modules.deskShare.controller.StartupCommand;
import org.bigbluebutton.modules.deskShare.controller.StopCommand;
import org.puremvc.as3.multicore.interfaces.IFacade;
import org.puremvc.as3.multicore.patterns.facade.Facade;
/**
* The DeskShareFacade is the facade class for the DeskShareModule
* @author Snap
*
*/
public class DeskShareFacade extends Facade implements IFacade
{
public static const NAME:String = "DeskShareFacade";
public static const STARTUP:String = "startup";
public static const STOP:String = "STOP";
/**
* The constructor. Note that this class should not be instanciated this way. Use the getInstance() method instead
*
*/
public function DeskShareFacade()
{
super(NAME);
}
/**
* Returns the singleton object for this class
* @return
*
*/
public static function getInstance():DeskShareFacade{
if (instanceMap[NAME] == null) instanceMap[NAME] = new DeskShareFacade();
return instanceMap[NAME] as DeskShareFacade;
}
override protected function initializeController():void{
super.initializeController();
registerCommand(STARTUP, StartupCommand);
registerCommand(STOP, StopCommand);
}
/**
* Executes the StartupCommand
* @param app
*
*/
public function startup(app:IBigBlueButtonModule):void{
sendNotification(STARTUP, app);
}
/**
* Executes the StopCommand
* @param app
*
*/
public function stop(app:IBigBlueButtonModule):void{
sendNotification(STOP, app);
removeCore(NAME);
}
}
}

View File

@ -0,0 +1,31 @@
package org.bigbluebutton.modules.deskShare
{
/**
* The constants for this module
* @author Snap
*
*/
public class DeskShareModuleConstants
{
public static const START:String = "start module";
public static const STOP:String = "stop module";
public static const CONNECTED:String = "connected to server";
public static const DISCONNECTED:String = "disconnected from server";
public static const OPEN_WINDOW:String = 'OPEN_WINDOW';
public static const CLOSE_WINDOW:String = 'CLOSE_WINDOW';
public static const ADD_WINDOW:String = 'ADD_WINDOW';
public static const REMOVE_WINDOW:String = 'REMOVE_WINDOW';
public static const START_VIEWING:String = "START_VIEWING";
public static const STOP_VIEWING:String = "STOP_VIEWING";
public static const SCALE:Number = 5;
public static const GOT_WIDTH:String = "GOT_WIDTH";
public static const GOT_HEIGHT:String = "GOT_HEIGHT";
public static const APPLET_STARTED:String = "APPLET_STARTED";
}
}

View File

@ -0,0 +1,18 @@
package org.bigbluebutton.modules.deskShare
{
import org.bigbluebutton.common.IBigBlueButtonModule;
import org.puremvc.as3.multicore.interfaces.IMediator;
import org.puremvc.as3.multicore.patterns.mediator.Mediator;
public class DeskShareModuleMediator extends Mediator implements IMediator
{
public static const NAME:String = "DeskShareModuleMediator";
private var _module:IBigBlueButtonModule;
public function DeskShareModuleMediator(module:IBigBlueButtonModule)
{
_module = module;
}
}
}

View File

@ -0,0 +1,35 @@
package org.bigbluebutton.modules.deskShare.controller
{
import org.bigbluebutton.modules.deskShare.DeskShareEndpointMediator;
import org.bigbluebutton.modules.deskShare.DeskShareModuleConstants;
import org.bigbluebutton.modules.deskShare.DeskShareModuleMediator;
import org.bigbluebutton.modules.deskShare.model.business.DeskShareProxy;
import org.bigbluebutton.modules.deskShare.view.DeskShareWindowMediator;
import org.puremvc.as3.multicore.interfaces.ICommand;
import org.puremvc.as3.multicore.interfaces.INotification;
import org.puremvc.as3.multicore.patterns.command.SimpleCommand;
/**
* The StartupCommand is called when the application is created and initialized
* This class in turn initializes all objects this module needs in order to run
* @author Snap
*
*/
public class StartupCommand extends SimpleCommand implements ICommand
{
/**
* The method which does all the initialization work
* @param notification
*
*/
override public function execute(notification:INotification):void{
var module:DeskShareModule = notification.getBody() as DeskShareModule;
facade.registerMediator(new DeskShareModuleMediator(module));
facade.registerMediator(new DeskShareEndpointMediator(module));
facade.registerMediator(new DeskShareWindowMediator(module));
facade.registerProxy(new DeskShareProxy(module));
sendNotification(DeskShareModuleConstants.CONNECTED);
}
}
}

View File

@ -0,0 +1,23 @@
package org.bigbluebutton.modules.deskShare.controller
{
import org.bigbluebutton.modules.deskShare.model.business.DeskShareProxy;
import org.puremvc.as3.multicore.interfaces.ICommand;
import org.puremvc.as3.multicore.interfaces.INotification;
import org.puremvc.as3.multicore.patterns.command.SimpleCommand;
/**
* This command is executed when the module stops. It's purpose is to shut down the module gracefully and release all the resources
* @author Snap
*
*/
public class StopCommand extends SimpleCommand implements ICommand
{
override public function execute(notification:INotification):void{
if (facade.hasProxy(DeskShareProxy.NAME)){
var proxy:DeskShareProxy = facade.retrieveProxy(DeskShareProxy.NAME) as DeskShareProxy;
proxy.stop();
}
}
}
}

View File

@ -0,0 +1,231 @@
package org.bigbluebutton.modules.deskShare.model.business
{
import flash.events.SyncEvent;
import flash.net.NetConnection;
import flash.net.Responder;
import flash.net.SharedObject;
import mx.controls.Alert;
import org.bigbluebutton.common.red5.Connection;
import org.bigbluebutton.common.red5.ConnectionEvent;
import org.bigbluebutton.modules.deskShare.DeskShareModuleConstants;
import org.bigbluebutton.modules.deskShare.model.vo.CaptureResolutionVO;
import org.puremvc.as3.multicore.interfaces.IProxy;
import org.puremvc.as3.multicore.patterns.proxy.Proxy;
/**
* The DeskShareProxy communicates with the Red5 deskShare server application
* @author Snap
*
*/
public class DeskShareProxy extends Proxy implements IProxy
{
public static const NAME:String = "DeskShareProxy";
//public static const URI:String = "rtmp://192.168.0.135/deskShare";
private var module:DeskShareModule;
private var conn:Connection;
private var nc:NetConnection;
private var deskSO:SharedObject;
private var responder:Responder;
/**
* The constructor.
* @param module - The DeskShareModule for which this class is a proxy
*
*/
public function DeskShareProxy(module:DeskShareModule)
{
super(NAME);
this.module = module;
conn = new Connection();
conn.addEventListener(Connection.SUCCESS, connectionSuccessHandler);
conn.addEventListener(Connection.FAILED, connectionFailedHandler);
conn.addEventListener(Connection.REJECTED, connectionRejectedHandler);
conn.setURI(module.uri);
conn.connect();
responder = new Responder(
function(result:Object):void{
if (result != null && (result as Boolean)){
checkVideoWidth();
checkVideoHeight();
}
},
function(status:Object):void{
LogUtil.error("Error while trying to call remote mathod on server");
}
);
}
/**
* Called when the application starts
* @not implemented
*
*/
public function start():void{
}
/**
* Called when the application stops
* @not implemented
*
*/
public function stop():void{
}
/**
* Called when a successful server connection is established
* @param e
*
*/
private function connectionSuccessHandler(e:ConnectionEvent):void{
nc = conn.getConnection();
deskSO = SharedObject.getRemote("deskSO", module.uri, false);
deskSO.addEventListener(SyncEvent.SYNC, sharedObjectSyncHandler);
deskSO.client = this;
deskSO.connect(nc);
checkIfStreamIsPublishing();
}
/**
* Returns the connection object which this object is using to communicate to the Red5 server
* @return - The NetConnection object
*
*/
public function getConnection():NetConnection{
return nc;
}
/**
* Called in case the connection to the server fails
* @param e
*
*/
public function connectionFailedHandler(e:ConnectionEvent):void{
Alert.show("connection failed " + e.toString());
}
/**
* Called in case the connection is rejected
* @param e
*
*/
public function connectionRejectedHandler(e:ConnectionEvent):void{
Alert.show("connection rejected " + e.toString());
}
/**
* A sync handler for the deskShare Shared Objects
* @param e
*
*/
public function sharedObjectSyncHandler(e:SyncEvent):void{
}
/**
* Invoked on the server once the clients' applet has started sharing and the server has started a video stream
*
*/
public function appletStarted():void{
sendNotification(DeskShareModuleConstants.APPLET_STARTED);
}
/**
* Call this method to send out a room-wide notification to start viewing the stream
*
*/
public function sendStartViewingNotification(captureWidth:Number, captureHeight:Number):void{
try{
deskSO.send("startViewing", captureWidth, captureHeight);
} catch(e:Error){
LogUtil.error("error while trying to send start viewing notification");
}
}
/**
* Called by the server when a notification is received to start viewing the broadcast stream .
* This method is called on successful execution of sendStartViewingNotification()
*
*/
public function startViewing(captureWidth:Number, captureHeight:Number):void{
sendNotification(DeskShareModuleConstants.START_VIEWING, new CaptureResolutionVO(captureWidth, captureHeight));
}
/**
* Sends a notification through the server to all the participants in the room to stop viewing the stream
*
*/
public function sendStopViewingNotification():void{
try{
deskSO.send("stopViewing");
} catch(e:Error){
LogUtil.error("could not send stop viewing notification");
}
}
/**
* Sends a notification to the module to stop viewing the stream
* This method is called on successful execution of sendStopViewingNotification()
*
*/
public function stopViewing():void{
sendNotification(DeskShareModuleConstants.STOP_VIEWING);
}
/**
* Check if anybody is publishing the stream for this room
* This method is useful for clients which have joined a room where somebody is already publishing
*
*/
private function checkIfStreamIsPublishing():void{
nc.call("checkIfStreamIsPublishing", responder);
}
/**
* Check what the width of the published video is
* This method is useful for clients which have joined a room where somebody is already publishing
*
*/
public function checkVideoWidth():void{
var widthResponder:Responder = new Responder(
function(result:Object):void{
if (result != null) sendNotification(DeskShareModuleConstants.GOT_WIDTH, result as Number);
},
function(status:Object):void{
LogUtil.error("Error while trying to call remote mathod on server");
}
);
nc.call("getVideoWidth", widthResponder);
}
/**
* Check what the height of the published video is
* This method is useful for clients which have joined a room where somebody is already publishing
*
*/
public function checkVideoHeight():void{
var heightResponder:Responder = new Responder(
function(result:Object):void{
//var resultString:String = "got result, it was " + (result as Number).toString();
//Alert.show(resultString);
if (result != null) sendNotification(DeskShareModuleConstants.GOT_HEIGHT, result as Number);
},
function(status:Object):void{
LogUtil.error("Error while trying to call remote mathod on server");
}
);
nc.call("getVideoHeight", heightResponder);
}
}
}

View File

@ -0,0 +1,21 @@
package org.bigbluebutton.modules.deskShare.model.business
{
import mx.controls.Alert;
import org.bigbluebutton.modules.deskShare.view.DeskShareWindowMediator;
public class StreamClient
{
private var mediator:DeskShareWindowMediator;
public function StreamClient(mediator:DeskShareWindowMediator)
{
this.mediator = mediator;
}
public function onMetaData(infoObject:Object):void {
Alert.show("got metadata");
}
}
}

View File

@ -0,0 +1,15 @@
package org.bigbluebutton.modules.deskShare.model.vo
{
public class CaptureResolutionVO
{
public var width:Number;
public var height:Number;
public function CaptureResolutionVO(width:Number, height:Number)
{
this.width = width;
this.height = height;
}
}
}

View File

@ -0,0 +1,263 @@
package org.bigbluebutton.modules.deskShare.view
{
import flash.events.AsyncErrorEvent;
import flash.events.Event;
import flash.external.ExternalInterface;
import flash.media.Video;
import flash.net.NetStream;
import mx.controls.Alert;
import mx.core.UIComponent;
import org.bigbluebutton.modules.deskShare.DeskShareModuleConstants;
import org.bigbluebutton.modules.deskShare.model.business.DeskShareProxy;
import org.bigbluebutton.modules.deskShare.model.vo.CaptureResolutionVO;
import org.bigbluebutton.modules.deskShare.view.components.DeskShareWindow;
import org.puremvc.as3.multicore.interfaces.IMediator;
import org.puremvc.as3.multicore.interfaces.INotification;
import org.puremvc.as3.multicore.patterns.mediator.Mediator;
/**
* The DeskShareWindowMediator is a mediator class for the DeskShareWindow. It listens to the window events and dispatches them accordingly
* @author Snap
*
*/
public class DeskShareWindowMediator extends Mediator implements IMediator
{
public static const NAME:String = "DeskShareWindowMediator";
public static const START_SHARING:String = "START_SHARING";
public static const START_VIEWING:String = "START_VIEWING";
private var _module:DeskShareModule;
private var _window:DeskShareWindow;
private var _deskShareWindowOpen:Boolean = false;
private var sharing:Boolean = false;
private var viewing:Boolean = false;
private var captureWidth:int;
private var captureHeight:int;
/**
* The default constructor
* @param module - the DeskShareModule to which the window belongs to
*
*/
public function DeskShareWindowMediator(module:DeskShareModule)
{
_module = module;
_window = new DeskShareWindow();
_window.name = _module.username;
_window.addEventListener(START_SHARING, onStartSharingEvent);
}
/**
* Lists the notifications to which this class should listen to
* @return
*
*/
override public function listNotificationInterests():Array{
return [
DeskShareModuleConstants.CLOSE_WINDOW,
DeskShareModuleConstants.OPEN_WINDOW,
DeskShareModuleConstants.START_VIEWING,
DeskShareModuleConstants.STOP_VIEWING,
DeskShareModuleConstants.GOT_HEIGHT,
DeskShareModuleConstants.GOT_WIDTH,
DeskShareModuleConstants.APPLET_STARTED
];
}
/**
* Handles the notifications to which this class listens to as they appear
* @param notification
*
*/
override public function handleNotification(notification:INotification):void{
switch(notification.getName()){
case DeskShareModuleConstants.CLOSE_WINDOW:
if (_deskShareWindowOpen){
facade.sendNotification(DeskShareModuleConstants.REMOVE_WINDOW, _window);
_deskShareWindowOpen = false;
}
break;
case DeskShareModuleConstants.OPEN_WINDOW:
_window.title = "Desk Share";
_window.showCloseButton = false;
_window.xPosition = 400;
_window.yPosition = 100;
facade.sendNotification(DeskShareModuleConstants.ADD_WINDOW, _window);
_deskShareWindowOpen = true;
break;
case DeskShareModuleConstants.START_VIEWING:
if (!sharing){
var capResVO:CaptureResolutionVO = notification.getBody() as CaptureResolutionVO;
_window.videoWidth = capResVO.width;
_window.videoHeight = capResVO.height;
startViewing();
}
break;
case DeskShareModuleConstants.STOP_VIEWING:
if (viewing) stopViewing();
break;
case DeskShareModuleConstants.GOT_HEIGHT:
_window.videoHeight = notification.getBody() as Number;
startViewing();
break;
case DeskShareModuleConstants.GOT_WIDTH:
_window.videoWidth = notification.getBody() as Number;
break;
case DeskShareModuleConstants.APPLET_STARTED:
if(sharing) onAppletStart();
break;
}
}
/**
* A convinience getter for the proxy of the module
* @return
*
*/
private function get proxy():DeskShareProxy{
return facade.retrieveProxy(DeskShareProxy.NAME) as DeskShareProxy;
}
private function startViewing():void{
_window.videoPlayer = new Video(_window.videoWidth, _window.videoHeight);
_window.videoPlayer.width = _window.videoWidth;
_window.videoPlayer.height = _window.videoHeight;
_window.videoHolder = new UIComponent();
_window.videoHolder.width = _window.videoWidth;
_window.videoHolder.height = _window.videoHeight;
_window.videoHolder.setActualSize(_window.videoWidth, _window.videoHeight);
_window.videoHolder.addChild(_window.videoPlayer);
_window.canvas.addChildAt(_window.videoHolder,0);
_window.videoHolder.x = 0;
_window.videoHolder.y = 20;
_window.dimensionsBox.visible = false;
_window.height = 600;//_window.videoHeight + 73;
_window.width = 500;//_window.videoWidth + 12;
_window.canvas.visible = true;
//_window.canvas.width = videoWidth;
//_window.canvas.height = videoHeight;
_window.ns = new NetStream(proxy.getConnection());
_window.ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
_window.ns.client = this;
_window.ns.bufferTime = 0;
_window.ns.receiveVideo(true);
_window.ns.receiveAudio(false);
_window.videoPlayer.attachNetStream(_window.ns);
var room:String = _module.getRoom();
_window.ns.play(room);
//_window.lblStatus.text = "You are viewing the desktop for presenter of room " + room;
_window.resizable = true;
viewing = true;
_window.btnStartApplet.visible = false;
_window.addZoomSlider();
_window.addDragSupport();
}
private function onAsyncError(e:AsyncErrorEvent):void{
}
/**
* Sends a call to the capture applet to stop broadcasting
*
*/
private function stopApplet():void{
ExternalInterface.call("stopApplet");
proxy.sendStopViewingNotification();
}
/**
* Stops the client from viewing the broadcast stream
*
*/
private function stopViewing():void{
_window.ns.close();
viewing = false;
_window.btnStartApplet.visible = true;
_window.canvas.visible = false;
_window.width = 236;
_window.height = 74;
_window.lblStatus.text = "";
_window.ns.close();
_window.canvas.removeChild(_window.videoHolder);
_window.videoHeight = 0;
_window.videoWidth = 0;
_window.width = _window.dimensionsBox.width + 7;
_window.height = _window.bar.height + _window.dimensionsBox.height + 33;
_window.dimensionsBox.visible = true;
_window.dimensionsBox.box.visible = true;
_window.resizable = false;
_window.removeZoomSlider();
_window.removeDragSupport();
}
/**
* Called when the start sharing button is pressed, this method calls javascript to start the capture applet
* @param e
*
*/
private function onStartSharingEvent(e:Event):void{
if (!sharing){
//Alert.show(_module.getRoom().toString());
var captureX:Number = _window.dimensionsBox.box.x * DeskShareModuleConstants.SCALE;
var captureY:Number = _window.dimensionsBox.box.y * DeskShareModuleConstants.SCALE;
captureWidth = Math.round(_window.dimensionsBox.box.width * DeskShareModuleConstants.SCALE - 5);
captureHeight = Math.round(_window.dimensionsBox.box.height * DeskShareModuleConstants.SCALE - 5);
sharing = true;
ExternalInterface.call("startApplet", _module.getCaptureServerUri(), _module.getRoom(),
captureX, captureY, captureWidth, captureHeight);
//ExternalInterface.addCallback("appletStartNotification", onAppletStart);
} else{
sharing = false;
_window.btnStartApplet.label = "Start Sharing";
_window.btnStartApplet.selected = false;
_window.width = _window.dimensionsBox.width + 7;
_window.height = _window.bar.height + _window.dimensionsBox.height + 33;
_window.dimensionsBox.stopThumbnail();
stopApplet();
}
}
/**
* Method called from the html template once the applet has started
*
*/
public function onAppletStart():void{
_window.capturing = true;
_window.height = _window.bar.height + _window.dimensionsBox.height + 33;
_window.width = _window.dimensionsBox.width + 7;
_window.btnStartApplet.label = "Stop Sharing";
//_window.lblStatus.text = "You are sharing your desktop with room " + _module.getRoom();
_window.dimensionsBox.x = 0;
_window.dimensionsBox.y = _window.bar.height + 5;
_window.dimensionsBox.startThumbnail(proxy.getConnection(), _module.getRoom());
//Send a notification to all room participants to start viewing the stream
proxy.sendStartViewingNotification(captureWidth, captureHeight);
}
/**
* Called when the start viewing button is pressed, this mathod starts viewing the stream
* @param e
*
*/
private function onStartViewingEvent(e:Event):void{
if (!viewing) startViewing();
else stopViewing();
}
}
}

View File

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<MDIWindow xmlns="flexlib.mdi.containers.*"
xmlns:mx="http://www.adobe.com/2006/mxml"
showCloseButton="false"
creationComplete="onCreationComplete()"
implements="org.bigbluebutton.common.IBbbModuleWindow" xmlns:components="org.bigbluebutton.modules.deskShare.view.components.*"
layout="absolute" resizable="false" verticalScrollPolicy="off" horizontalScrollPolicy="off">
<mx:Script>
<![CDATA[
import mx.controls.HSlider;
import mx.controls.VSlider;
import mx.events.SliderEvent;
import mx.events.ResizeEvent;
import org.bigbluebutton.modules.deskShare.view.DeskShareWindowMediator;
import mx.controls.Alert;
import mx.core.UIComponent;
import org.bigbluebutton.modules.deskShare.model.business.DeskShareProxy;
private var _xPosition:int;
private var _yPosition:int;
public var proxy:DeskShareProxy;
public var videoHolder:UIComponent;
public var videoPlayer:Video;
public var ns:NetStream;
public var capturing:Boolean = false;
public var videoWidth:Number = 400;
public var videoHeight:Number = 300;
private var zoomSlider:HSlider;
private var startDragX:Number;
private var startDragY:Number;
private var startDragMouseX:Number;
private var startDragMouseY:Number;
public function get xPosition():int{
return _xPosition;
}
public function get yPosition():int{
return _yPosition;
}
public function set xPosition(x:int):void{
_xPosition = x;
}
public function set yPosition(y:int):void{
_yPosition = y;
}
private function onCreationComplete():void{
if (ExternalInterface.call("checkForJava") != 1){
//Alert.show("Java is not enabled in your browser. Desktop Sharing will not work");
this.enabled = false;
this.lblStatus.text = "Java not enabled";
}
height = bar.height + dimensionsBox.height + 33;
width = dimensionsBox.width + 7;
dimensionsBox.y = bar.height + 5;
}
public function addZoomSlider():void{
zoomSlider = new HSlider();
zoomSlider.minimum = 10;
zoomSlider.maximum = 100;
zoomSlider.value = 100;
zoomSlider.labels = ['10%','100%'];
zoomSlider.addEventListener(SliderEvent.CHANGE, onZoomChange);
bar.addChildAt(zoomSlider, bar.numChildren - 1);
}
public function removeZoomSlider():void{
bar.removeChild(zoomSlider);
}
public function addDragSupport():void{
canvas.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
canvas.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
public function removeDragSupport():void{
canvas.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
canvas.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
private function onZoomChange(e:SliderEvent):void{
videoPlayer.width = zoomSlider.value/100 * videoWidth;
videoPlayer.height = zoomSlider.value/100 * videoHeight;
videoHolder.width = zoomSlider.value/100 * videoWidth;
videoHolder.height = zoomSlider.value/100 * videoHeight;
}
private function onMouseDown(e:MouseEvent):void{
startDragX = this.mouseX;
startDragY = this.mouseY;
canvas.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
canvas.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
}
private function onMouseMove(e:MouseEvent):void{
var movedX:Number = this.mouseX - startDragX;
var movedY:Number = this.mouseY - startDragY;
canvas.verticalScrollPosition -= movedY;
canvas.horizontalScrollPosition -= movedX;
}
private function onMouseUp(e:MouseEvent):void{
canvas.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
canvas.removeEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
}
private function onMouseOut(e:MouseEvent):void{
canvas.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
canvas.removeEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
}
]]>
</mx:Script>
<mx:Canvas id="canvas" x="0" y="50" visible="false" width="100%" height="100%"/>
<mx:ApplicationControlBar id="bar" width="100%">
<mx:RadioButton id="btnStartApplet" label="Start Sharing" click="dispatchEvent(new Event(DeskShareWindowMediator.START_SHARING))" x="10" y="10"/>
<mx:Label id="lblStatus" />
</mx:ApplicationControlBar>
<components:DimensionsBox id="dimensionsBox"/>
</MDIWindow>

View File

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="onCreationComplete()"
backgroundColor="gray" toolTip="Drag the black box to the area of the screen you wish to share"
xmlns:components="org.bigbluebutton.modules.deskShare.view.components.*">
<mx:Script>
<![CDATA[
import org.bigbluebutton.modules.deskShare.DeskShareModuleConstants;
import mx.core.UIComponent;
private var screenWidth:Number;
private var screenHeight:Number;
private var startDragX:Number;
private var startDragY:Number;
private var startDragMouseX:Number;
private var startDragMouseY:Number;
public var videoHolder:UIComponent;
private var videoPlayer:Video;
private var ns:NetStream;
[Bindable]
private var suggestedFrameRate:Number;
[Bindable]
private var suggestedQuality:String;
private function onCreationComplete():void{
screenWidth = Capabilities.screenResolutionX;
screenHeight = Capabilities.screenResolutionY;
this.width = Math.round(screenWidth / DeskShareModuleConstants.SCALE);
this.height = Math.round(screenHeight / DeskShareModuleConstants.SCALE);
updateBoxInfo();
}
public function startThumbnail(nc:NetConnection, streamName:String):void{
this.visible = true;
box.visible = false;
videoHolder = new UIComponent();
videoPlayer = new Video(box.width, box.height);
videoPlayer.width = box.width;
videoPlayer.height = box.height;
videoHolder.width = box.width;
videoHolder.height = box.height;
videoHolder.setActualSize(box.width, box.height);
videoHolder.addChild(videoPlayer);
this.addChild(videoHolder);
videoHolder.x = box.x;
videoHolder.y = box.y;
videoHolder.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
videoHolder.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
this.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
ns = new NetStream(nc);
ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
ns.client = this;
ns.bufferTime = 0;
ns.receiveVideo(true);
ns.receiveAudio(false);
videoPlayer.attachNetStream(ns);
ns.play(streamName);
}
public function stopThumbnail():void{
this.removeChild(videoHolder);
videoPlayer.clear();
videoPlayer = null;
videoHolder = null;
this.removeEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
box.visible = true;
}
private function onMouseDown(e:MouseEvent):void{
startDragX = videoHolder.x;
startDragY = videoHolder.y;
startDragMouseX = this.mouseX;
startDragMouseY = this.mouseY;
videoHolder.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}
private function onMouseMove(e:MouseEvent):void{
var newX:Number = startDragX + (this.mouseX - startDragMouseX);
var newY:Number = startDragY + (this.mouseY - startDragMouseY);
if (newX < 0) videoHolder.x = 0;
else if (newX > this.width - (box.width+5)) videoHolder.x = this.width - box.width;
else videoHolder.x = newX;
if (newY < 0) videoHolder.y = 0;
else if (newY > this.height - (box.height+5)) videoHolder.y = this.height - box.height;
else videoHolder.y = newY;
ExternalInterface.call("setScreenCoordinates", getXPosition(), getYPosition());
}
private function onMouseUp(e:MouseEvent):void{
videoHolder.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}
private function onMouseOut(e:MouseEvent):void{
videoHolder.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}
private function getXPosition():Number{
return videoHolder.x * DeskShareModuleConstants.SCALE;
}
private function getYPosition():Number{
return videoHolder.y * DeskShareModuleConstants.SCALE;
}
private function onAsyncError(e:AsyncErrorEvent):void{
}
private function updateBoxInfo():void{
if (box.width *DeskShareModuleConstants.SCALE >= Capabilities.screenResolutionX) lblWidth.text
= Capabilities.screenResolutionX.toString();
if (box.height*DeskShareModuleConstants.SCALE >= Capabilities.screenResolutionY) lblHeight.text
= Capabilities.screenResolutionY.toString();
var area:Number = (box.width*DeskShareModuleConstants.SCALE) * (box.height*DeskShareModuleConstants.SCALE);
if (area > 1000000){
suggestedFrameRate = 1;
suggestedQuality = "Poor";
} else if (area > 600000){
suggestedFrameRate = 2;
suggestedQuality = "Fair"
} else if (area > 300000){
suggestedFrameRate = 4;
suggestedQuality = "Good"
} else if (area > 150000){
suggestedFrameRate = 8;
suggestedQuality = "Excellent";
} else{
suggestedFrameRate = 10;
suggestedQuality = "Excellent";
}
}
]]>
</mx:Script>
<components:ResizableBox id="box" x="10" y="10" resize="updateBoxInfo()" useHandCursor="true"
width="{(Math.round((Capabilities.screenResolutionX/2)/DeskShareModuleConstants.SCALE))}"
height="{(Math.round((Capabilities.screenResolutionY - 100)/DeskShareModuleConstants.SCALE))}"
minWidth="{Math.round(300/DeskShareModuleConstants.SCALE)}"
minHeight="{Math.round(300/DeskShareModuleConstants.SCALE)}"
maxWidth="{Math.round((Capabilities.screenResolutionX)/DeskShareModuleConstants.SCALE)}"
maxHeight="{Math.round((Capabilities.screenResolutionY)/DeskShareModuleConstants.SCALE)}"
verticalScrollPolicy="off" horizontalScrollPolicy="off">
<mx:HBox horizontalGap="0">
<mx:Label id="lblWidth" text="{(box.width * DeskShareModuleConstants.SCALE).toString()}"/>
<mx:Label text="x"/>
<mx:Label id="lblHeight" text="{(box.height * DeskShareModuleConstants.SCALE).toString()}"/>
</mx:HBox>
<mx:HBox>
<mx:Label text="FrameRate: " />
<mx:Label text="{suggestedFrameRate}" />
</mx:HBox>
<mx:HBox>
<mx:Label text="Quality: " />
<mx:Label text="{suggestedQuality}" />
</mx:HBox>
</components:ResizableBox>
</mx:Canvas>

View File

@ -0,0 +1,189 @@
package org.bigbluebutton.modules.deskShare.view.components
{
import flash.display.Graphics;
import flash.events.Event;
import flash.events.MouseEvent;
import mx.controls.Button;
import mx.core.UIComponent;
/**
* Similar to the ResizeManager, this class adds support for moving a component by dragging it
* with the mouse.
*
* @author Chris Callendar
* @date March 17th, 2009
*/
public class MoveManager
{
private const MOVE_HANDLE_WIDTH:int = 6;
private const MOVE_HANDLE_HEIGHT:int = 14;
private var _moveHandle:UIComponent;
// the component that is being moved
private var moveComponent:UIComponent;
// the component that when dragged causes the above component to move
private var dragComponent:UIComponent;
// the component that the move handle is added to
private var moveHandleParent:UIComponent;
private var dragging:Boolean;
private var _enabled:Boolean;
public function MoveManager() {
dragging = false;
_enabled = true;
}
public function get enabled():Boolean {
return _enabled;
}
public function set enabled(en:Boolean):void {
if (en != _enabled) {
_enabled = en;
moveHandle.visible = en;
}
}
/**
* Adds support for moving a component.
* @param moveComponent the component that will have its x and y values changed
* @param dragComponent the component that will have a mouse_down listener added to listen
* for when the user drags it. If null then the moveComponent is used instead.
* @param moveHandleParent the parent component which will have the move handle added to it.
* If null then it is added to the moveComponent.
*/
public function addMoveSupport(moveComponent:UIComponent, dragComponent:UIComponent = null,
moveHandleParent:UIComponent = null):void {
this.moveComponent = moveComponent;
this.dragComponent = dragComponent;
this.moveHandleParent = moveHandleParent;
if (moveHandleParent) {
moveHandleParent.addChildAt(moveHandle, 0);
} else if (moveComponent) {
moveComponent.addChildAt(moveHandle, 0);
}
if (dragComponent) {
dragComponent.addEventListener(MouseEvent.MOUSE_DOWN, dragComponentMouseDown);
} else if (moveComponent) {
moveComponent.addEventListener(MouseEvent.MOUSE_DOWN, dragComponentMouseDown);
}
}
/**
* Removes move support, removes the mouse listener and the move handle.
*/
public function removeMoveSupport():void {
if (dragComponent) {
dragComponent.removeEventListener(MouseEvent.MOUSE_DOWN, dragComponentMouseDown);
} else if (moveComponent) {
moveComponent.removeEventListener(MouseEvent.MOUSE_DOWN, dragComponentMouseDown);
}
if (moveHandleParent) {
moveHandleParent.removeChild(moveHandle);
} else if (moveComponent) {
//moveComponent.removeChild(moveHandle);
}
}
/**
* Returns the move handle component.
*/
public function get moveHandle():UIComponent {
if (_moveHandle == null) {
_moveHandle = new UIComponent();
_moveHandle.width = MOVE_HANDLE_WIDTH;
_moveHandle.height = MOVE_HANDLE_HEIGHT;
}
return _moveHandle;
}
/**
* Draws a 6x14 move/drag handle.
*/
public function drawMoveHandle(parentW:Number, parentH:Number, color:uint = 0x666666, alpha:Number = 1):void {
if (enabled) {
var g:Graphics = moveHandle.graphics;
g.clear();
var xx:int = 2;
var yy:int = 2;
for (var i:int = 0; i < 4; i++) {
drawDot(g, color, alpha, xx, yy + (i * 4));
//drawDot(g, color, alpha, xx + 4, yy + (i * 4));
}
}
}
/**
* Draws a single (2x2) dot.
*/
private function drawDot(g:Graphics, color:uint, alpha:Number, xx:Number, yy:Number, w:Number = 2, h:Number = 2):void {
g.lineStyle(0, 0, 0);
g.beginFill(color, alpha);
g.drawRect(xx, yy, w, h);
g.endFill();
}
/**
* This function gets called when the user presses down the mouse button on the
* dragComponent (or if not specified then the moveComponent).
* It starts the drag process.
*/
private function dragComponentMouseDown(event:MouseEvent):void {
if (!enabled) {
return;
}
// special case - ignore if the target is a button (e.g. close button)
if (event.target is Button) {
return;
}
// move above all others
if (moveComponent.parent) {
var index:int = moveComponent.parent.getChildIndex(moveComponent);
var last:int = moveComponent.parent.numChildren - 1;
if (index != last) {
moveComponent.parent.setChildIndex(moveComponent, last);
}
}
moveComponent.startDrag();
moveComponent.systemManager.addEventListener(MouseEvent.MOUSE_MOVE, dragComponentMove);
moveComponent.systemManager.addEventListener(MouseEvent.MOUSE_UP, dragComponentMouseUp);
moveComponent.systemManager.stage.addEventListener(Event.MOUSE_LEAVE, dragComponentMouseUp);
}
private function dragComponentMove(event:MouseEvent):void {
if (!dragging) {
dragging = true;
moveComponent.clearStyle("top");
moveComponent.clearStyle("right");
moveComponent.clearStyle("bottom");
moveComponent.clearStyle("left");
moveComponent.dispatchEvent(new Event("dragStart"));
}
moveComponent.dispatchEvent(new Event("drag"));
if (moveComponent.parent.width < moveComponent.x + moveComponent.width) moveComponent.x = moveComponent.parent.width - moveComponent.width;
if (moveComponent.parent.height< moveComponent.y + moveComponent.height)moveComponent.y = moveComponent.parent.height- moveComponent.height;
if (moveComponent.x < 0) moveComponent.x = 0;
if (moveComponent.y < 0) moveComponent.y = 0;
}
private function dragComponentMouseUp(event:Event):void {
moveComponent.stopDrag();
if (dragging) {
dragging = false;
moveComponent.dispatchEvent(new Event("dragEnd"));
}
moveComponent.systemManager.removeEventListener(MouseEvent.MOUSE_MOVE, dragComponentMove);
moveComponent.systemManager.removeEventListener(MouseEvent.MOUSE_UP, dragComponentMouseUp);
moveComponent.systemManager.stage.removeEventListener(Event.MOUSE_LEAVE, dragComponentMouseUp);
}
}
}

View File

@ -0,0 +1,130 @@
package org.bigbluebutton.modules.deskShare.view.components
{
import flash.events.MouseEvent;
import mx.containers.Box;
import mx.containers.BoxDirection;
import mx.styles.CSSStyleDeclaration;
import mx.styles.StyleManager;
/**
* The alpha value for the resize handle.
* @default 0x666666
*/
[Style(name="resizeHandleColor", type="Color", inherit="no")]
/**
* The alpha value for the resize handle.
* @default 1
*/
[Style(name="resizeHandleAlpha", type="Number", inherit="no")]
/**
* Extends the Box class to let the user resize the box by dragging on a small
* 16x16 resize handle in the bottom right corner of the box.
*
* See the ResizeManager class for more details.
*
* You can also specify the minWidth, minHeight, maxWidth, and maxHeight properties
* to restrict the size of the box.
*
* <pre>
* &lt;ResizableBox
* <strong>Styles</strong>
* resizeHandleColor="0x666666"
* resizeHandleAlpha="1"
* &gt;
* ...
* <i>child tags</i>
* ...
* &lt;/ui:ResizableBox&gt;
* </pre>
*
* @author Chris Callendar
* @date March 17th, 2009
*/
public class ResizableBox extends Box
{
// setup the default styles
private static var classConstructed:Boolean = classConstruct();
private static function classConstruct():Boolean {
var style:CSSStyleDeclaration = StyleManager.getStyleDeclaration("ResizableBox");
if (!style) {
style = new CSSStyleDeclaration();
}
style.defaultFactory = function():void {
this.resizeHandleColor = 0x666666;
this.resizeHandleAlpha = 1;
this.resizeHandleColor = 0x00ff00;
this.backgroundColor = 0xddffdd;
this.backgroundAlpha = 0.3;
this.borderThickness = 1;
this.borderStyle = "solid";
this.borderColor = 0x000000;
};
StyleManager.setStyleDeclaration("ResizableBox", style, true);
return true;
};
private var resizeManager:ResizeManager;
private var moveManager:MoveManager;
public function ResizableBox() {
super();
this.resizeManager = new ResizeManager(this);
this.moveManager = new MoveManager();
this.moveManager.addMoveSupport(this,null,null);
this.resizeManager.resizeHandle.addEventListener(MouseEvent.MOUSE_OVER, onMouseOverResizeHandle);
this.resizeManager.resizeHandle.addEventListener(MouseEvent.MOUSE_OUT, onMouseOutResizeHandle);
direction = BoxDirection.VERTICAL;
// set a minimum size for this box
minWidth = 24;
minHeight = 24;
}
public function onMouseOverResizeHandle(e:MouseEvent):void{
this.moveManager.removeMoveSupport();
}
public function onMouseOutResizeHandle(e:MouseEvent):void{
this.moveManager.addMoveSupport(this, null, null);
}
[Inspectable(category="Common")]
public function get resizable():Boolean {
return resizeManager.enabled;
}
public function set resizable(resize:Boolean):void {
resizeManager.enabled = resize;
}
override public function styleChanged(styleProp:String):void {
super.styleChanged(styleProp);
if ((styleProp == "resizeHandleColor") || (styleProp == "resizeHandleAlpha")) {
invalidateDisplayList();
}
}
override protected function updateDisplayList(w:Number, h:Number):void {
super.updateDisplayList(w, h);
// Draw resize handle
var color:uint = uint(getStyle("resizeHandleColor"));
var alpha:Number = Number(getStyle("resizeHandleAlpha"));
resizeManager.drawResizeHandle(w, h, color, alpha);
}
override public function validateDisplayList():void {
super.validateDisplayList();
// prevent the scrollbars from covering up the resize handle
if (horizontalScrollBar || verticalScrollBar) {
resizeManager.adjustScrollBars(horizontalScrollBar, verticalScrollBar);
}
}
}
}

View File

@ -0,0 +1,271 @@
package org.bigbluebutton.modules.deskShare.view.components
{
import flash.display.Graphics;
import flash.events.MouseEvent;
import mx.controls.scrollClasses.ScrollBar;
import mx.core.Container;
import mx.core.IChildList;
import mx.core.UIComponent;
/**
* Utility class for allowing containers to be resized by a resize handle.
* Adds a small resize handle to a parent UIComponent. This resize handle will
* cause the parent UIComponent to be resized when the user drags the handle.
*
* @author Chris Callendar
* @date March 17th, 2009
*/
public class ResizeManager
{
private const RESIZE_HANDLE_SIZE:int = 16;
private var resizeInitX:Number = 0;
private var resizeInitY:Number = 0;
private var _resizeHandle:UIComponent;
private var _enabled:Boolean;
private var repaint:Boolean;
private var lastColor:uint = 0x0;
private var lastAlpha:Number = 0;
private var parent:UIComponent;
public function ResizeManager(parent:UIComponent) {
this.parent = parent;
this._enabled = true;
repaint = true;
}
public function get enabled():Boolean {
return _enabled;
}
public function set enabled(en:Boolean):void {
if (en != _enabled) {
_enabled = en;
resizeHandle.visible = en;
}
}
/**
* Returns the resizeHandle UIComponent.
*/
public function get resizeHandle():UIComponent {
if (_resizeHandle == null) {
_resizeHandle = new UIComponent();
_resizeHandle.mouseEnabled = true;
_resizeHandle.addEventListener(MouseEvent.MOUSE_DOWN, resizeHandler);
_resizeHandle.width = RESIZE_HANDLE_SIZE;
_resizeHandle.height = RESIZE_HANDLE_SIZE;
_resizeHandle.toolTip = "Drag this handle to resize the component";
}
return _resizeHandle;
}
/**
* Checks if the horizontal and/or vertical scrollbars are showing, if so it resizes
* them to make sure the resize handle isn't covered up.
* If the component is a ScrollControlBase, then you have to pass in the scrollbars
* since they are protected properties.
*/
public function adjustScrollBars(hScroll:ScrollBar, vScroll:ScrollBar):void {
if (enabled) {
// keep the resize handle on top, also adds it to the parent
moveResizeHandleOnTop();
// make room for the resize handle, only needed if one scrollbar is showing
var hScrollShowing:Boolean = hScroll && hScroll.visible;
var vScrollShowing:Boolean = vScroll && vScroll.visible;
if (hScrollShowing && vScrollShowing) {
// do nothing, there is already a white square between the ends of the scrollbars
// where the resize handle is, so no need to resize the scrollbars
} else if (hScrollShowing) {
// important - use setActualSize instead of the width/height properties otherwise
// we get into an endless loop
hScroll.setActualSize(Math.max(hScroll.minWidth, hScroll.width - resizeHandle.width), hScroll.height);
} else if (vScrollShowing) {
vScroll.setActualSize(vScroll.width, Math.max(vScroll.minHeight, vScroll.height - resizeHandle.height));
}
}
}
/**
* Positions the resize handle in the bottom right corner of the parent container.
* @param parentW the parent container's width
* @param parentH the parent container's height
*/
private function positionResizeHandle(parentW:Number, parentH:Number):void {
if (enabled && (parentW >= resizeHandle.width) && (parentH >= resizeHandle.height)) {
var newX:Number = parentW - resizeHandle.width;
var newY:Number = parentH - resizeHandle.height;
if ((newX != resizeHandle.x) || (newY != resizeHandle.y)) {
resizeHandle.move(newX, newY);
repaint = true;
}
if (!resizeHandle.visible) {
resizeHandle.visible = true;
repaint = true;
}
} else {
resizeHandle.visible = false;
}
}
/**
* Draws the resize handle in the bottom right corner of the parent container.
* @param parentW the parent container's width
* @param parentH the parent container's height
* @param color the color for the resize handle
*/
public function drawResizeHandle(parentW:Number, parentH:Number, color:uint = 0x666666, alpha:Number = 1):void {
// Draw resize handle
if (enabled && (parentW >= resizeHandle.width) && (parentH >= resizeHandle.height)) {
// keep the resize handle on top, also adds it to the parent
moveResizeHandleOnTop();
// ensure that the resize handle is correctly positioned in the bottom right corner
positionResizeHandle(parentW, parentH);
if (repaint || (color != lastColor) || (alpha != lastAlpha)) {
repaint = false;
lastColor = color;
lastAlpha = alpha;
var g:Graphics = resizeHandle.graphics;
g.clear();
var offset:int = 4;
// for mouse dragging only, draw a transparent triangle around the handle
var bgAlpha:Number = 0;
drawResizeArea(g, color, bgAlpha, 0, 0, resizeHandle.width - 1, resizeHandle.height - 1);
// now draw the resize handle dots (6 dots making up a triangle)
drawResizeDot(g, color, alpha, offset, offset + 8);
drawResizeDot(g, color, alpha, offset + 4, offset + 8);
drawResizeDot(g, color, alpha, offset + 8, offset + 8);
drawResizeDot(g, color, alpha, offset + 4, offset + 4);
drawResizeDot(g, color, alpha, offset + 8, offset + 4);
drawResizeDot(g, color, alpha, offset + 8, offset);
}
} else {
resizeHandle.visible = false;
}
}
/**
* Makes sure that the resizeHandle has been added to the parent, and also makes sure it is
* the last item in the child list.
*/
private function moveResizeHandleOnTop():void {
var children:IChildList = (parent is Container ? (parent as Container).rawChildren : parent);
var index:int = (resizeHandle.parent != null ? children.getChildIndex(resizeHandle) : -1);
if (index != (children.numChildren - 1)) {
// make sure the resize handle is on top
if (index == -1) {
children.addChild(resizeHandle);
} else {
children.setChildIndex(resizeHandle, children.numChildren - 1);
}
repaint = true;
}
}
/**
* Draws a triangle region around the resize handle.
* This makes it so that the mouse down event works properly.
* @param color the color for the background
* @param xx the x position of the resize handle
* @param yy the y position of the resize handle
* @param w the width of the resize handle
* @param h the height of the resize handle
*/
private function drawResizeArea(g:Graphics, color:uint, alpha:Number,
xx:Number, yy:Number, w:Number, h:Number):void {
// no border
g.lineStyle(0, 0, 0);
// fill the background, set alpha=0 to make it transparent
g.beginFill(color, alpha);
// draw a triangle
g.moveTo(xx, yy + h);
g.lineTo(xx + w, yy + h);
g.lineTo(xx + w, yy);
g.lineTo(xx, yy + h);
g.endFill();
}
/**
* Draws a single resize dot, defaults to a 2x2 rectangle.
* @param color the color for the resize dot
* @param xx the x position for the dot
* @param yy the y position for the dot
* @param w the width of the dot (defaults to 2)
* @param h the height of dot (defaults to 2)
*/
private function drawResizeDot(g:Graphics, color:uint, alpha:Number,
xx:Number, yy:Number, w:Number = 2, h:Number = 2):void {
// no border
g.lineStyle(0, 0, 0);
// fill the dot
g.beginFill(color, alpha);
g.drawRect(xx, yy, w, h);
g.endFill();
}
// Resize event handler
private function resizeHandler(event:MouseEvent):void {
if (enabled) {
startResize(event.stageX, event.stageY);
}
}
private function startResize(globalX:Number, globalY:Number):void {
resizeInitX = globalX;
resizeInitY = globalY;
// Add event handlers so that the SystemManager handles the mouseMove and mouseUp events.
// Set useCapure flag to true to handle these events
// during the capture phase so no other component tries to handle them.
parent.systemManager.addEventListener(MouseEvent.MOUSE_MOVE, resizeMouseMoveHandler, true);
parent.systemManager.addEventListener(MouseEvent.MOUSE_UP, resizeMouseUpHandler, true);
}
/**
* Resizes this panel as the user moves the mouse with the mouse button down.
* Also restricts the width and height based on the parent's minWidth, maxWidth, minHeight, and
* maxHeight properties.
*/
private function resizeMouseMoveHandler(event:MouseEvent):void {
event.stopImmediatePropagation();
var newWidth:Number = parent.width + event.stageX - resizeInitX;
var newHeight:Number = parent.height + event.stageY - resizeInitY;
// restrict the width/height
if ((newWidth >= parent.minWidth) && (newWidth <= parent.maxWidth)) {
parent.width = newWidth;
}
if ((newHeight >= parent.minHeight) && (newHeight <= parent.maxHeight)) {
parent.height = newHeight;
}
resizeInitX = event.stageX;
resizeInitY = event.stageY;
if (parent.parent.width < parent.x + parent.width) parent.x = parent.parent.width - parent.width;
if (parent.parent.height< parent.y + parent.height)parent.y = parent.parent.height- parent.height;
if (parent.x < 0) parent.x = 0;
if (parent.y < 0) parent.y = 0;
}
/**
* Removes the event handlers from the SystemManager.
*/
private function resizeMouseUpHandler(event:MouseEvent):void {
event.stopImmediatePropagation();
parent.systemManager.removeEventListener(MouseEvent.MOUSE_MOVE, resizeMouseMoveHandler, true);
parent.systemManager.removeEventListener(MouseEvent.MOUSE_UP, resizeMouseUpHandler, true);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB