- 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:
parent
4bc66fdb61
commit
cdbe88f2a0
@ -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>
|
||||
|
BIN
bigbluebutton-client/html-template/deskShare.jar
Normal file
BIN
bigbluebutton-client/html-template/deskShare.jar
Normal file
Binary file not shown.
@ -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"
|
||||
|
96
bigbluebutton-client/src/DeskShareModule.mxml
Normal file
96
bigbluebutton-client/src/DeskShareModule.mxml
Normal 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>
|
@ -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>
|
||||
|
||||
|
@ -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>
|
@ -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>
|
@ -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{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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";
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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>
|
@ -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>
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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>
|
||||
* <ResizableBox
|
||||
* <strong>Styles</strong>
|
||||
* resizeHandleColor="0x666666"
|
||||
* resizeHandleAlpha="1"
|
||||
* >
|
||||
* ...
|
||||
* <i>child tags</i>
|
||||
* ...
|
||||
* </ui:ResizableBox>
|
||||
* </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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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 |
Loading…
Reference in New Issue
Block a user