first pass at multi whiteboard cursors
This commit is contained in:
parent
b6176ac736
commit
09ec1e6151
@ -76,7 +76,6 @@ public interface IBigBlueButtonInGW {
|
||||
void clear(String meetingID);
|
||||
void removePresentation(String meetingID, String presentationID);
|
||||
void getPresentationInfo(String meetingID, String requesterID, String replyTo);
|
||||
void sendCursorUpdate(String meetingID, double xPercent, double yPercent);
|
||||
void resizeAndMoveSlide(String meetingID, double xOffset, double yOffset, double widthRatio, double heightRatio);
|
||||
void gotoSlide(String meetingID, String page);
|
||||
void sharePresentation(String meetingID, String presentationID, boolean share);
|
||||
@ -111,6 +110,7 @@ public interface IBigBlueButtonInGW {
|
||||
|
||||
// Whiteboard
|
||||
void sendWhiteboardAnnotation(String meetingID, String requesterID, java.util.Map<String, Object> annotation);
|
||||
void sendCursorPosition(String meetingID, String requesterID, double xPercent, double yPercent);
|
||||
void requestWhiteboardAnnotationHistory(String meetingID, String requesterID, String whiteboardId, String replyTo);
|
||||
void clearWhiteboard(String meetingID, String requesterID, String whiteboardId);
|
||||
void undoWhiteboard(String meetingID, String requesterID, String whiteboardId);
|
||||
|
@ -10,7 +10,6 @@ import org.bigbluebutton.common.messages.RemovePresentationMessage;
|
||||
import org.bigbluebutton.common.messages.ResizeAndMoveSlideMessage;
|
||||
import org.bigbluebutton.common.messages.SendConversionCompletedMessage;
|
||||
import org.bigbluebutton.common.messages.SendConversionUpdateMessage;
|
||||
import org.bigbluebutton.common.messages.SendCursorUpdateMessage;
|
||||
import org.bigbluebutton.common.messages.SendPageCountErrorMessage;
|
||||
import org.bigbluebutton.common.messages.SendSlideGeneratedMessage;
|
||||
import org.bigbluebutton.common.messages.SharePresentationMessage;
|
||||
@ -118,9 +117,6 @@ public class PresentationMessageListener implements MessageHandler {
|
||||
} else if (RemovePresentationMessage.REMOVE_PRESENTATION.equals(messageName)) {
|
||||
RemovePresentationMessage msg = RemovePresentationMessage.fromJson(message);
|
||||
bbbInGW.removePresentation(msg.meetingId, msg.presentationId);
|
||||
} else if (SendCursorUpdateMessage.SEND_CURSOR_UPDATE.equals(messageName)) {
|
||||
SendCursorUpdateMessage msg = SendCursorUpdateMessage.fromJson(message);
|
||||
bbbInGW.sendCursorUpdate(msg.meetingId, msg.xPercent, msg.yPercent);
|
||||
} else if (SharePresentationMessage.SHARE_PRESENTATION.equals(messageName)) {
|
||||
SharePresentationMessage msg = SharePresentationMessage.fromJson(message);
|
||||
bbbInGW.sharePresentation(msg.meetingId, msg.presentationId, msg.share);
|
||||
|
@ -7,6 +7,7 @@ import org.bigbluebutton.common.messages.ModifyWhiteboardAccessRequestMessage;
|
||||
import org.bigbluebutton.common.messages.GetWhiteboardAccessRequestMessage;
|
||||
import org.bigbluebutton.common.messages.MessagingConstants;
|
||||
import org.bigbluebutton.common.messages.RequestWhiteboardAnnotationHistoryRequestMessage;
|
||||
import org.bigbluebutton.common.messages.SendCursorPositionMessage;
|
||||
import org.bigbluebutton.common.messages.SendWhiteboardAnnotationRequestMessage;
|
||||
import org.bigbluebutton.common.messages.UndoWhiteboardRequest;
|
||||
import org.bigbluebutton.core.api.IBigBlueButtonInGW;
|
||||
@ -52,6 +53,9 @@ public class WhiteboardMessageReceiver implements MessageHandler {
|
||||
} else if (SendWhiteboardAnnotationRequestMessage.SEND_WHITEBOARD_ANNOTATION_REQUEST.equals(messageName)) {
|
||||
SendWhiteboardAnnotationRequestMessage msg = SendWhiteboardAnnotationRequestMessage.fromJson(message);
|
||||
bbbInGW.sendWhiteboardAnnotation(msg.meetingId, msg.requesterId, msg.annotation);
|
||||
} else if (SendCursorPositionMessage.SEND_CURSOR_POSITION.equals(messageName)) {
|
||||
SendCursorPositionMessage msg = SendCursorPositionMessage.fromJson(message);
|
||||
bbbInGW.sendCursorPosition(msg.meetingId, msg.requesterId, msg.xPercent, msg.yPercent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,13 +18,17 @@
|
||||
*/
|
||||
package org.bigbluebutton.core.recorders.events;
|
||||
|
||||
public class CursorUpdateRecordEvent extends AbstractPresentationRecordEvent{
|
||||
public class CursorUpdateRecordEvent extends AbstractWhiteboardRecordEvent{
|
||||
|
||||
public CursorUpdateRecordEvent() {
|
||||
super();
|
||||
setEvent("CursorMoveEvent");
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
eventMap.put("userId", userId);
|
||||
}
|
||||
|
||||
public void setXPercent(double percent) {
|
||||
eventMap.put("xOffset", Double.toString(percent));
|
||||
}
|
||||
|
@ -367,10 +367,6 @@ class BigBlueButtonInGW(
|
||||
eventBus.publish(BigBlueButtonEvent(meetingID, new GetPresentationInfo(meetingID, requesterID, replyTo)))
|
||||
}
|
||||
|
||||
def sendCursorUpdate(meetingID: String, xPercent: Double, yPercent: Double) {
|
||||
eventBus.publish(BigBlueButtonEvent(meetingID, new SendCursorUpdate(meetingID, xPercent, yPercent)))
|
||||
}
|
||||
|
||||
def resizeAndMoveSlide(meetingID: String, xOffset: Double, yOffset: Double, widthRatio: Double, heightRatio: Double) {
|
||||
eventBus.publish(BigBlueButtonEvent(meetingID, new ResizeAndMoveSlide(meetingID, xOffset, yOffset, widthRatio, heightRatio)))
|
||||
}
|
||||
@ -466,6 +462,10 @@ class BigBlueButtonInGW(
|
||||
}
|
||||
}
|
||||
|
||||
def sendCursorPosition(meetingID: String, requesterID: String, xPercent: Double, yPercent: Double) {
|
||||
eventBus.publish(BigBlueButtonEvent(meetingID, new SendCursorPositionRequest(meetingID, requesterID, xPercent, yPercent)))
|
||||
}
|
||||
|
||||
def requestWhiteboardAnnotationHistory(meetingID: String, requesterID: String, whiteboardId: String, replyTo: String) {
|
||||
eventBus.publish(BigBlueButtonEvent(meetingID, new GetWhiteboardShapesRequest(meetingID, requesterID, whiteboardId, replyTo)))
|
||||
}
|
||||
|
@ -86,7 +86,6 @@ class MessageSenderActor(val service: MessageSender)
|
||||
case msg: ClearPresentationOutMsg => handleClearPresentationOutMsg(msg)
|
||||
case msg: RemovePresentationOutMsg => handleRemovePresentationOutMsg(msg)
|
||||
case msg: GetPresentationInfoOutMsg => handleGetPresentationInfoOutMsg(msg)
|
||||
case msg: SendCursorUpdateOutMsg => handleSendCursorUpdateOutMsg(msg)
|
||||
case msg: ResizeAndMoveSlideOutMsg => handleResizeAndMoveSlideOutMsg(msg)
|
||||
case msg: GotoSlideOutMsg => handleGotoSlideOutMsg(msg)
|
||||
case msg: SharePresentationOutMsg => handleSharePresentationOutMsg(msg)
|
||||
@ -137,6 +136,7 @@ class MessageSenderActor(val service: MessageSender)
|
||||
case msg: LockLayoutEvent => handleLockLayoutEvent(msg)
|
||||
case msg: GetWhiteboardShapesReply => handleGetWhiteboardShapesReply(msg)
|
||||
case msg: SendWhiteboardAnnotationEvent => handleSendWhiteboardAnnotationEvent(msg)
|
||||
case msg: CursorPositionUpdatedEvent => handleCursorPositionUpdatedEvent(msg)
|
||||
case msg: ClearWhiteboardEvent => handleClearWhiteboardEvent(msg)
|
||||
case msg: UndoWhiteboardEvent => handleUndoWhiteboardEvent(msg)
|
||||
case msg: ModifiedWhiteboardAccessEvent => handleModifiedWhiteboardAccessEvent(msg)
|
||||
@ -381,11 +381,6 @@ class MessageSenderActor(val service: MessageSender)
|
||||
service.send(MessagingConstants.FROM_PRESENTATION_CHANNEL, json)
|
||||
}
|
||||
|
||||
private def handleSendCursorUpdateOutMsg(msg: SendCursorUpdateOutMsg) {
|
||||
val json = PesentationMessageToJsonConverter.sendCursorUpdateOutMsgToJson(msg)
|
||||
service.send(MessagingConstants.FROM_PRESENTATION_CHANNEL, json)
|
||||
}
|
||||
|
||||
private def handleResizeAndMoveSlideOutMsg(msg: ResizeAndMoveSlideOutMsg) {
|
||||
val json = PesentationMessageToJsonConverter.resizeAndMoveSlideOutMsgToJson(msg)
|
||||
service.send(MessagingConstants.FROM_PRESENTATION_CHANNEL, json)
|
||||
@ -748,6 +743,11 @@ class MessageSenderActor(val service: MessageSender)
|
||||
service.send(MessagingConstants.FROM_WHITEBOARD_CHANNEL, json)
|
||||
}
|
||||
|
||||
private def handleCursorPositionUpdatedEvent(msg: CursorPositionUpdatedEvent) {
|
||||
val json = WhiteboardMessageToJsonConverter.cursorPositionUpdatedEventToJson(msg)
|
||||
service.send(MessagingConstants.FROM_WHITEBOARD_CHANNEL, json)
|
||||
}
|
||||
|
||||
private def handleClearWhiteboardEvent(msg: ClearWhiteboardEvent) {
|
||||
val json = WhiteboardMessageToJsonConverter.clearWhiteboardEventToJson(msg)
|
||||
service.send(MessagingConstants.FROM_WHITEBOARD_CHANNEL, json)
|
||||
|
@ -66,7 +66,6 @@ class RecorderActor(val recorder: RecorderApplication)
|
||||
case msg: ClearPublicChatHistoryReply => handleClearPublicChatHistoryReply(msg)
|
||||
case msg: ClearPresentationOutMsg => handleClearPresentationOutMsg(msg)
|
||||
case msg: RemovePresentationOutMsg => handleRemovePresentationOutMsg(msg)
|
||||
case msg: SendCursorUpdateOutMsg => handleSendCursorUpdateOutMsg(msg)
|
||||
case msg: ResizeAndMoveSlideOutMsg => handleResizeAndMoveSlideOutMsg(msg)
|
||||
case msg: GotoSlideOutMsg => handleGotoSlideOutMsg(msg)
|
||||
case msg: SharePresentationOutMsg => handleSharePresentationOutMsg(msg)
|
||||
@ -86,6 +85,7 @@ class RecorderActor(val recorder: RecorderApplication)
|
||||
case msg: VoiceRecordingStarted => handleVoiceRecordingStarted(msg)
|
||||
case msg: VoiceRecordingStopped => handleVoiceRecordingStopped(msg)
|
||||
case msg: SendWhiteboardAnnotationEvent => handleSendWhiteboardAnnotationEvent(msg)
|
||||
case msg: CursorPositionUpdatedEvent => handleCursorPositionUpdatedEvent(msg)
|
||||
case msg: ClearWhiteboardEvent => handleClearWhiteboardEvent(msg)
|
||||
case msg: UndoWhiteboardEvent => handleUndoWhiteboardEvent(msg)
|
||||
case msg: EditCaptionHistoryReply => handleEditCaptionHistoryReply(msg)
|
||||
@ -196,18 +196,6 @@ class RecorderActor(val recorder: RecorderApplication)
|
||||
}
|
||||
}
|
||||
|
||||
private def handleSendCursorUpdateOutMsg(msg: SendCursorUpdateOutMsg) {
|
||||
if (msg.recorded) {
|
||||
val event = new CursorUpdateRecordEvent();
|
||||
event.setMeetingId(msg.meetingID);
|
||||
event.setTimestamp(TimestampGenerator.generateTimestamp);
|
||||
event.setXPercent(msg.xPercent);
|
||||
event.setYPercent(msg.yPercent);
|
||||
|
||||
recorder.record(msg.meetingID, event);
|
||||
}
|
||||
}
|
||||
|
||||
private def handleEndAndKickAll(msg: EndAndKickAll): Unit = {
|
||||
if (msg.recorded) {
|
||||
val ev = new ParticipantEndAndKickAllRecordEvent();
|
||||
@ -444,6 +432,19 @@ class RecorderActor(val recorder: RecorderApplication)
|
||||
|
||||
}
|
||||
|
||||
private def handleCursorPositionUpdatedEvent(msg: CursorPositionUpdatedEvent) {
|
||||
if (msg.recorded) {
|
||||
val event = new CursorUpdateRecordEvent();
|
||||
event.setMeetingId(msg.meetingID);
|
||||
event.setTimestamp(TimestampGenerator.generateTimestamp);
|
||||
event.setUserId(msg.requesterID);
|
||||
event.setXPercent(msg.xPercent);
|
||||
event.setYPercent(msg.yPercent);
|
||||
|
||||
recorder.record(msg.meetingID, event);
|
||||
}
|
||||
}
|
||||
|
||||
private def handleClearWhiteboardEvent(msg: ClearWhiteboardEvent) {
|
||||
if (msg.recorded) {
|
||||
val event = new ClearPageWhiteboardRecordEvent()
|
||||
|
@ -137,7 +137,6 @@ case class BroadcastLayoutRequest(meetingID: String, requesterID: String, layout
|
||||
case class ClearPresentation(meetingID: String) extends InMessage
|
||||
case class RemovePresentation(meetingID: String, presentationID: String) extends InMessage
|
||||
case class GetPresentationInfo(meetingID: String, requesterID: String, replyTo: String) extends InMessage
|
||||
case class SendCursorUpdate(meetingID: String, xPercent: Double, yPercent: Double) extends InMessage
|
||||
case class ResizeAndMoveSlide(meetingID: String, xOffset: Double, yOffset: Double,
|
||||
widthRatio: Double, heightRatio: Double) extends InMessage
|
||||
case class GotoSlide(meetingID: String, page: String) extends InMessage
|
||||
@ -194,6 +193,7 @@ case class VoiceConfRecordingStartedMessage(voiceConfId: String, recordStream: S
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
case class SendWhiteboardAnnotationRequest(meetingID: String, requesterID: String, annotation: AnnotationVO) extends InMessage
|
||||
case class SendCursorPositionRequest(meetingID: String, requesterID: String, xPercent: Double, yPercent: Double) extends InMessage
|
||||
case class GetWhiteboardShapesRequest(meetingID: String, requesterID: String, whiteboardId: String, replyTo: String) extends InMessage
|
||||
case class ClearWhiteboardRequest(meetingID: String, requesterID: String, whiteboardId: String) extends InMessage
|
||||
case class UndoWhiteboardRequest(meetingID: String, requesterID: String, whiteboardId: String) extends InMessage
|
||||
|
@ -62,7 +62,6 @@ object MessageNames {
|
||||
val PRESENTATION_PAGE_COUNT_ERROR = "presentation_page_count_error_message"
|
||||
val PRESENTATION_SLIDE_GENERATED = "presentation_slide_generated_message"
|
||||
val PRESENTATION_CONVERSION_COMPLETED = "presentation_conversion_completed_message"
|
||||
val PRESENTATION_CURSOR_UPDATED = "presentation_cursor_updated_message"
|
||||
val SEND_VOICE_USERS_REQUEST = "send_voice_users_request"
|
||||
val MUTE_MEETING_REQUEST = "mute_meeting_request"
|
||||
val IS_MEETING_MUTED = "is_meeting_muted_request"
|
||||
@ -163,6 +162,7 @@ object MessageNames {
|
||||
val PRESENTATION_PAGE_GENERATED = "presentation_page_generated_message"
|
||||
val GET_WHITEBOARD_SHAPES_REPLY = "get_whiteboard_shapes_reply"
|
||||
val SEND_WHITEBOARD_SHAPE = "send_whiteboard_shape_message"
|
||||
val CURSOR_POSITION_UPDATED = "cursor_position_updated_message"
|
||||
val UNDO_WHITEBOARD_MESSAGE = "undo_whiteboard_message"
|
||||
val MODIFIED_WHITEBOARD_ACCESS = "modified_whiteboard_access_message"
|
||||
val GET_WHITEBOARD_ACCESS_REPLY = "get_whiteboard_access_reply"
|
||||
|
@ -108,7 +108,6 @@ case class ClearPresentationOutMsg(meetingID: String, recorded: Boolean) extends
|
||||
case class RemovePresentationOutMsg(meetingID: String, recorded: Boolean, presentationID: String) extends IOutMessage
|
||||
case class GetPresentationInfoOutMsg(meetingID: String, recorded: Boolean, requesterID: String,
|
||||
info: CurrentPresentationInfo, replyTo: String) extends IOutMessage
|
||||
case class SendCursorUpdateOutMsg(meetingID: String, recorded: Boolean, xPercent: Double, yPercent: Double) extends IOutMessage
|
||||
case class ResizeAndMoveSlideOutMsg(meetingID: String, recorded: Boolean, page: Page) extends IOutMessage
|
||||
case class GotoSlideOutMsg(meetingID: String, recorded: Boolean, page: Page) extends IOutMessage
|
||||
case class SharePresentationOutMsg(meetingID: String, recorded: Boolean, presentation: Presentation) extends IOutMessage
|
||||
@ -145,6 +144,7 @@ case class GetCurrentPollReplyMessage(meetingID: String, recorded: Boolean, requ
|
||||
// Whiteboard
|
||||
case class GetWhiteboardShapesReply(meetingID: String, recorded: Boolean, requesterID: String, whiteboardId: String, shapes: Array[AnnotationVO], replyTo: String) extends IOutMessage
|
||||
case class SendWhiteboardAnnotationEvent(meetingID: String, recorded: Boolean, requesterID: String, whiteboardId: String, shape: AnnotationVO) extends IOutMessage
|
||||
case class CursorPositionUpdatedEvent(meetingID: String, recorded: Boolean, requesterID: String, xPercent: Double, yPercent: Double) extends IOutMessage
|
||||
case class ClearWhiteboardEvent(meetingID: String, recorded: Boolean, requesterID: String, whiteboardId: String, fullClear: Boolean) extends IOutMessage
|
||||
case class UndoWhiteboardEvent(meetingID: String, recorded: Boolean, requesterID: String, whiteboardId: String, shapeId: String) extends IOutMessage
|
||||
case class ModifiedWhiteboardAccessEvent(meetingID: String, recorded: Boolean, requesterID: String, multiUser: Boolean) extends IOutMessage
|
||||
|
@ -11,8 +11,6 @@ trait PresentationApp {
|
||||
|
||||
val outGW: OutMessageGateway
|
||||
|
||||
private var cursorLocation = new CursorLocation
|
||||
|
||||
def handlePreuploadedPresentations(msg: PreuploadedPresentations) {
|
||||
val pres = msg.presentations
|
||||
|
||||
@ -83,11 +81,6 @@ trait PresentationApp {
|
||||
outGW.send(new GetPresentationInfoOutMsg(mProps.meetingID, mProps.recorded, msg.requesterID, presentationInfo, msg.replyTo))
|
||||
}
|
||||
|
||||
def handleSendCursorUpdate(msg: SendCursorUpdate) {
|
||||
cursorLocation = new CursorLocation(msg.xPercent, msg.yPercent)
|
||||
outGW.send(new SendCursorUpdateOutMsg(mProps.meetingID, mProps.recorded, msg.xPercent, msg.yPercent))
|
||||
}
|
||||
|
||||
def handleResizeAndMoveSlide(msg: ResizeAndMoveSlide) {
|
||||
// Force coordinate that are out-of-bounds inside valid values
|
||||
val xOffset = if (msg.xOffset <= 0) msg.xOffset else 0
|
||||
|
@ -2,7 +2,6 @@ package org.bigbluebutton.core.apps
|
||||
|
||||
case class CurrentPresenter(userId: String, name: String, assignedBy: String)
|
||||
case class CurrentPresentationInfo(presenter: CurrentPresenter, presentations: Seq[Presentation])
|
||||
case class CursorLocation(xPercent: Double = 0D, yPercent: Double = 0D)
|
||||
case class Presentation(id: String, name: String, current: Boolean = false,
|
||||
pages: scala.collection.immutable.HashMap[String, Page], downloadable: Boolean)
|
||||
|
||||
|
@ -47,6 +47,10 @@ trait WhiteboardApp {
|
||||
|
||||
}
|
||||
|
||||
def handleSendCursorPositionRequest(msg: SendCursorPositionRequest) {
|
||||
outGW.send(new CursorPositionUpdatedEvent(mProps.meetingID, mProps.recorded, msg.requesterID, msg.xPercent, msg.yPercent))
|
||||
}
|
||||
|
||||
def handleGetWhiteboardShapesRequest(msg: GetWhiteboardShapesRequest) {
|
||||
//println("WB: Received page history [" + msg.whiteboardId + "]")
|
||||
val history = liveMeeting.wbModel.getHistory(msg.whiteboardId);
|
||||
|
@ -3,7 +3,6 @@ package org.bigbluebutton.core.apps
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bigbluebutton.core.util.jhotdraw.BezierWrapper
|
||||
import org.bigbluebutton.core.util.jhotdraw.PathData
|
||||
|
||||
import scala.collection.immutable.List
|
||||
import scala.collection.immutable.HashMap
|
||||
|
@ -85,16 +85,6 @@ object PesentationMessageToJsonConverter {
|
||||
Util.buildJson(header, payload)
|
||||
}
|
||||
|
||||
def sendCursorUpdateOutMsgToJson(msg: SendCursorUpdateOutMsg): String = {
|
||||
val payload = new java.util.HashMap[String, Any]()
|
||||
payload.put(Constants.MEETING_ID, msg.meetingID)
|
||||
payload.put(Constants.X_PERCENT, msg.xPercent)
|
||||
payload.put(Constants.Y_PERCENT, msg.yPercent)
|
||||
|
||||
val header = Util.buildHeader(MessageNames.PRESENTATION_CURSOR_UPDATED, None)
|
||||
Util.buildJson(header, payload)
|
||||
}
|
||||
|
||||
def resizeAndMoveSlideOutMsgToJson(msg: ResizeAndMoveSlideOutMsg): String = {
|
||||
val payload = new java.util.HashMap[String, Any]()
|
||||
payload.put(Constants.MEETING_ID, msg.meetingID)
|
||||
|
@ -53,6 +53,17 @@ object WhiteboardMessageToJsonConverter {
|
||||
Util.buildJson(header, payload)
|
||||
}
|
||||
|
||||
def cursorPositionUpdatedEventToJson(msg: CursorPositionUpdatedEvent): String = {
|
||||
val payload = new java.util.HashMap[String, Any]()
|
||||
payload.put(Constants.MEETING_ID, msg.meetingID)
|
||||
payload.put(Constants.REQUESTER_ID, msg.requesterID)
|
||||
payload.put(Constants.X_PERCENT, msg.xPercent)
|
||||
payload.put(Constants.Y_PERCENT, msg.yPercent)
|
||||
|
||||
val header = Util.buildHeader(MessageNames.CURSOR_POSITION_UPDATED, None)
|
||||
Util.buildJson(header, payload)
|
||||
}
|
||||
|
||||
def clearWhiteboardEventToJson(msg: ClearWhiteboardEvent): String = {
|
||||
val payload = new java.util.HashMap[String, Any]()
|
||||
payload.put(Constants.MEETING_ID, msg.meetingID)
|
||||
|
@ -97,13 +97,13 @@ class MeetingActor(val mProps: MeetingProperties,
|
||||
case msg: PresentationConversionCompleted => handlePresentationConversionCompleted(msg)
|
||||
case msg: RemovePresentation => handleRemovePresentation(msg)
|
||||
case msg: GetPresentationInfo => handleGetPresentationInfo(msg)
|
||||
case msg: SendCursorUpdate => handleSendCursorUpdate(msg)
|
||||
case msg: ResizeAndMoveSlide => handleResizeAndMoveSlide(msg)
|
||||
case msg: GotoSlide => handleGotoSlide(msg)
|
||||
case msg: SharePresentation => handleSharePresentation(msg)
|
||||
case msg: GetSlideInfo => handleGetSlideInfo(msg)
|
||||
case msg: PreuploadedPresentations => handlePreuploadedPresentations(msg)
|
||||
case msg: SendWhiteboardAnnotationRequest => handleSendWhiteboardAnnotationRequest(msg)
|
||||
case msg: SendCursorPositionRequest => handleSendCursorPositionRequest(msg)
|
||||
case msg: GetWhiteboardShapesRequest => handleGetWhiteboardShapesRequest(msg)
|
||||
case msg: ClearWhiteboardRequest => handleClearWhiteboardRequest(msg)
|
||||
case msg: UndoWhiteboardRequest => handleUndoWhiteboardRequest(msg)
|
||||
|
@ -4,16 +4,18 @@ import java.util.HashMap;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
public class PresentationCursorUpdateMessage implements ISubscribedMessage {
|
||||
public static final String PRESENTATION_CURSOR_UPDATED = "presentation_cursor_updated_message";
|
||||
public class CursorPositionUpdatedMessage implements ISubscribedMessage {
|
||||
public static final String CURSOR_POSITION_UPDATED = "cursor_position_updated_message";
|
||||
public final String VERSION = "0.0.1";
|
||||
|
||||
public final String meetingId;
|
||||
public final String requesterId;
|
||||
public final double xPercent;
|
||||
public final double yPercent;
|
||||
|
||||
public PresentationCursorUpdateMessage(String meetingId, double xPercent, double yPercent) {
|
||||
public CursorPositionUpdatedMessage(String meetingId, String requesterId, double xPercent, double yPercent) {
|
||||
this.meetingId = meetingId;
|
||||
this.requesterId = requesterId;
|
||||
this.xPercent = xPercent;
|
||||
this.yPercent = yPercent;
|
||||
}
|
||||
@ -21,15 +23,16 @@ public class PresentationCursorUpdateMessage implements ISubscribedMessage {
|
||||
public String toJson() {
|
||||
HashMap<String, Object> payload = new HashMap<String, Object>();
|
||||
payload.put(Constants.MEETING_ID, meetingId);
|
||||
payload.put(Constants.REQUESTER_ID, requesterId);
|
||||
payload.put(Constants.X_PERCENT, xPercent);
|
||||
payload.put(Constants.Y_PERCENT, yPercent);
|
||||
|
||||
java.util.HashMap<String, Object> header = MessageBuilder.buildHeader(PRESENTATION_CURSOR_UPDATED, VERSION, null);
|
||||
java.util.HashMap<String, Object> header = MessageBuilder.buildHeader(CURSOR_POSITION_UPDATED, VERSION, null);
|
||||
|
||||
return MessageBuilder.buildJson(header, payload);
|
||||
}
|
||||
|
||||
public static PresentationCursorUpdateMessage fromJson(String message) {
|
||||
public static CursorPositionUpdatedMessage fromJson(String message) {
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject obj = (JsonObject) parser.parse(message);
|
||||
|
||||
@ -39,15 +42,17 @@ public class PresentationCursorUpdateMessage implements ISubscribedMessage {
|
||||
|
||||
if (header.has("name")) {
|
||||
String messageName = header.get("name").getAsString();
|
||||
if (PRESENTATION_CURSOR_UPDATED.equals(messageName)) {
|
||||
if (CURSOR_POSITION_UPDATED.equals(messageName)) {
|
||||
if (payload.has(Constants.MEETING_ID)
|
||||
&& payload.has(Constants.REQUESTER_ID)
|
||||
&& payload.has(Constants.X_PERCENT)
|
||||
&& payload.has(Constants.Y_PERCENT)) {
|
||||
String meetingId = payload.get(Constants.MEETING_ID).getAsString();
|
||||
String requesterId = payload.get(Constants.REQUESTER_ID).getAsString();
|
||||
double xPercent = payload.get(Constants.X_PERCENT).getAsDouble();
|
||||
double yPercent = payload.get(Constants.Y_PERCENT).getAsDouble();
|
||||
|
||||
return new PresentationCursorUpdateMessage(meetingId, xPercent, yPercent);
|
||||
return new CursorPositionUpdatedMessage(meetingId, requesterId, xPercent, yPercent);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,16 +5,18 @@ import java.util.HashMap;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
public class SendCursorUpdateMessage implements IBigBlueButtonMessage {
|
||||
public static final String SEND_CURSOR_UPDATE = "send_cursor_update";
|
||||
public class SendCursorPositionMessage implements IBigBlueButtonMessage {
|
||||
public static final String SEND_CURSOR_POSITION = "send_cursor_position";
|
||||
public static final String VERSION = "0.0.1";
|
||||
|
||||
public final String meetingId;
|
||||
public final String requesterId;
|
||||
public final double xPercent;
|
||||
public final double yPercent;
|
||||
|
||||
public SendCursorUpdateMessage(String meetingId, double xPercent, double yPercent){
|
||||
public SendCursorPositionMessage(String meetingId, String requesterId, double xPercent, double yPercent){
|
||||
this.meetingId = meetingId;
|
||||
this.requesterId = requesterId;
|
||||
this.xPercent = xPercent;
|
||||
this.yPercent = yPercent;
|
||||
}
|
||||
@ -22,15 +24,16 @@ public class SendCursorUpdateMessage implements IBigBlueButtonMessage {
|
||||
public String toJson() {
|
||||
HashMap<String, Object> payload = new HashMap<String, Object>();
|
||||
payload.put(Constants.MEETING_ID, meetingId);
|
||||
payload.put(Constants.REQUESTER_ID, requesterId);
|
||||
payload.put(Constants.X_PERCENT, xPercent);
|
||||
payload.put(Constants.Y_PERCENT, yPercent);
|
||||
|
||||
java.util.HashMap<String, Object> header = MessageBuilder.buildHeader(SEND_CURSOR_UPDATE, VERSION, null);
|
||||
java.util.HashMap<String, Object> header = MessageBuilder.buildHeader(SEND_CURSOR_POSITION, VERSION, null);
|
||||
|
||||
return MessageBuilder.buildJson(header, payload);
|
||||
}
|
||||
|
||||
public static SendCursorUpdateMessage fromJson(String message) {
|
||||
public static SendCursorPositionMessage fromJson(String message) {
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject obj = (JsonObject) parser.parse(message);
|
||||
|
||||
@ -40,15 +43,17 @@ public class SendCursorUpdateMessage implements IBigBlueButtonMessage {
|
||||
|
||||
if (header.has("name")) {
|
||||
String messageName = header.get("name").getAsString();
|
||||
if (SEND_CURSOR_UPDATE.equals(messageName)) {
|
||||
if (SEND_CURSOR_POSITION.equals(messageName)) {
|
||||
if (payload.has(Constants.MEETING_ID)
|
||||
&& payload.has(Constants.REQUESTER_ID)
|
||||
&& payload.has(Constants.X_PERCENT)
|
||||
&& payload.has(Constants.Y_PERCENT)) {
|
||||
String meetingId = payload.get(Constants.MEETING_ID).getAsString();
|
||||
String requesterId = payload.get(Constants.REQUESTER_ID).getAsString();
|
||||
double xPercent = payload.get(Constants.X_PERCENT).getAsDouble();
|
||||
double yPercent = payload.get(Constants.Y_PERCENT).getAsDouble();
|
||||
|
||||
return new SendCursorUpdateMessage(meetingId, xPercent, yPercent);
|
||||
return new SendCursorPositionMessage(meetingId, requesterId, xPercent, yPercent);
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,6 @@ import org.bigbluebutton.common.messages.GoToSlideReplyMessage;
|
||||
import org.bigbluebutton.common.messages.PresentationConversionDoneMessage;
|
||||
import org.bigbluebutton.common.messages.PresentationConversionErrorMessage;
|
||||
import org.bigbluebutton.common.messages.PresentationConversionProgressMessage;
|
||||
import org.bigbluebutton.common.messages.PresentationCursorUpdateMessage;
|
||||
import org.bigbluebutton.common.messages.PresentationPageGeneratedReplyMessage;
|
||||
import org.bigbluebutton.common.messages.PresentationPageResizedMessage;
|
||||
import org.bigbluebutton.common.messages.PresentationRemovedMessage;
|
||||
@ -55,9 +54,6 @@ public class PresentationClientMessageSender {
|
||||
case PresentationPageGeneratedReplyMessage.PRESENTATION_PAGE_GENERATED:
|
||||
processPresentationPageGeneratedReply(message);
|
||||
break;
|
||||
case PresentationCursorUpdateMessage.PRESENTATION_CURSOR_UPDATED:
|
||||
processPresentationCursorUpdate(message);
|
||||
break;
|
||||
case PresentationConversionErrorMessage.PRESENTATION_CONVERSION_ERROR:
|
||||
processPresentationConversionError(message);
|
||||
break;
|
||||
@ -227,23 +223,6 @@ public class PresentationClientMessageSender {
|
||||
}
|
||||
}
|
||||
|
||||
private void processPresentationCursorUpdate(String json) {
|
||||
PresentationCursorUpdateMessage msg = PresentationCursorUpdateMessage.fromJson(json);
|
||||
if (msg != null) {
|
||||
Map<String, Object> args = new HashMap<String, Object>();
|
||||
args.put("meetingID", msg.meetingId);
|
||||
args.put("xPercent", msg.xPercent);
|
||||
args.put("yPercent", msg.yPercent);
|
||||
|
||||
Map<String, Object> message = new HashMap<String, Object>();
|
||||
Gson gson = new Gson();
|
||||
message.put("msg", gson.toJson(args));
|
||||
|
||||
BroadcastClientMessage m = new BroadcastClientMessage(msg.meetingId, "PresentationCursorUpdateCommand", message);
|
||||
service.sendMessage(m);
|
||||
}
|
||||
}
|
||||
|
||||
private void processPresentationPageGeneratedReply(String json) {
|
||||
PresentationPageGeneratedReplyMessage msg = PresentationPageGeneratedReplyMessage.fromJson(json);
|
||||
if (msg != null) {
|
||||
|
@ -4,6 +4,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bigbluebutton.common.messages.ClearWhiteboardReplyMessage;
|
||||
import org.bigbluebutton.common.messages.CursorPositionUpdatedMessage;
|
||||
import org.bigbluebutton.common.messages.GetWhiteboardShapesReplyMessage;
|
||||
import org.bigbluebutton.common.messages.GetWhiteboardAccessReplyMessage;
|
||||
import org.bigbluebutton.common.messages.SendWhiteboardAnnotationReplyMessage;
|
||||
@ -59,6 +60,12 @@ public class WhiteboardClientMessageSender {
|
||||
processSendWhiteboardAnnotationReplyMessage(swarm);
|
||||
}
|
||||
break;
|
||||
case CursorPositionUpdatedMessage.CURSOR_POSITION_UPDATED:
|
||||
CursorPositionUpdatedMessage cpum = CursorPositionUpdatedMessage.fromJson(message);
|
||||
if (cpum != null) {
|
||||
processCursorPositionUpdatedMessage(cpum);
|
||||
}
|
||||
break;
|
||||
case ModifiedWhiteboardAccessMessage.MODIFIED_WHITEBOARD_ACCESS:
|
||||
ModifiedWhiteboardAccessMessage mwam = ModifiedWhiteboardAccessMessage.fromJson(message);
|
||||
if (mwam != null) {
|
||||
@ -101,6 +108,20 @@ public class WhiteboardClientMessageSender {
|
||||
|
||||
}
|
||||
|
||||
private void processCursorPositionUpdatedMessage(CursorPositionUpdatedMessage msg) {
|
||||
Map<String, Object> args = new HashMap<String, Object>();
|
||||
args.put("requesterId", msg.requesterId);
|
||||
args.put("xPercent", msg.xPercent);
|
||||
args.put("yPercent", msg.yPercent);
|
||||
|
||||
Map<String, Object> message = new HashMap<String, Object>();
|
||||
Gson gson = new Gson();
|
||||
message.put("msg", gson.toJson(args));
|
||||
|
||||
BroadcastClientMessage m = new BroadcastClientMessage(msg.meetingId, "WhiteboardCursorPositionUpdatedCommand", message);
|
||||
service.sendMessage(m);
|
||||
}
|
||||
|
||||
private void processGetWhiteboardShapesReplyMessage(GetWhiteboardShapesReplyMessage msg) {
|
||||
|
||||
Map<String, Object> args = new HashMap<String, Object>();
|
||||
|
@ -180,11 +180,6 @@ public class MessagePublisher {
|
||||
|
||||
}
|
||||
|
||||
public void sendCursorUpdate(String meetingID, double xPercent, double yPercent) {
|
||||
SendCursorUpdateMessage msg = new SendCursorUpdateMessage(meetingID, xPercent, yPercent);
|
||||
sender.send(MessagingConstants.TO_PRESENTATION_CHANNEL, msg.toJson());
|
||||
}
|
||||
|
||||
public void resizeAndMoveSlide(String meetingID, double xOffset, double yOffset, double widthRatio, double heightRatio) {
|
||||
ResizeAndMoveSlideMessage msg = new ResizeAndMoveSlideMessage(meetingID, xOffset, yOffset, widthRatio, heightRatio);
|
||||
sender.send(MessagingConstants.TO_PRESENTATION_CHANNEL, msg.toJson());
|
||||
@ -262,11 +257,17 @@ public class MessagePublisher {
|
||||
DeskShareGetInfoRequestMessage msg = new DeskShareGetInfoRequestMessage(meetingID, requesterID, replyTo);
|
||||
sender.send(MessagingConstants.FROM_VOICE_CONF_SYSTEM_CHAN, msg.toJson());
|
||||
}
|
||||
|
||||
public void sendWhiteboardAnnotation(String meetingID, String requesterID, Map<String, Object> annotation) {
|
||||
SendWhiteboardAnnotationRequestMessage msg = new SendWhiteboardAnnotationRequestMessage(meetingID, requesterID, annotation);
|
||||
sender.send(MessagingConstants.TO_WHITEBOARD_CHANNEL, msg.toJson());
|
||||
}
|
||||
|
||||
public void sendCursorPosition(String meetingID, String requesterID, double xPercent, double yPercent) {
|
||||
SendCursorPositionMessage msg = new SendCursorPositionMessage(meetingID, requesterID, xPercent, yPercent);
|
||||
sender.send(MessagingConstants.TO_WHITEBOARD_CHANNEL, msg.toJson());
|
||||
}
|
||||
|
||||
public void requestWhiteboardAnnotationHistory(String meetingID, String requesterID, String whiteboardId, String replyTo) {
|
||||
RequestWhiteboardAnnotationHistoryRequestMessage msg = new RequestWhiteboardAnnotationHistoryRequestMessage(meetingID, requesterID, whiteboardId, replyTo);
|
||||
sender.send(MessagingConstants.TO_WHITEBOARD_CHANNEL, msg.toJson());
|
||||
|
@ -77,11 +77,6 @@ public class PresentationApplication {
|
||||
red5BBBInGW.getPresentationInfo(meetingID, requesterID, replyTo);
|
||||
}
|
||||
|
||||
public void sendCursorUpdate(String meetingID, Double xPercent, Double yPercent) {
|
||||
|
||||
red5BBBInGW.sendCursorUpdate(meetingID, xPercent, yPercent);
|
||||
}
|
||||
|
||||
public void resizeAndMoveSlide(String meetingID, Double xOffset, Double yOffset, Double widthRatio, Double heightRatio) {
|
||||
|
||||
red5BBBInGW.resizeAndMoveSlide(meetingID, xOffset, yOffset, widthRatio, heightRatio);
|
||||
|
@ -73,29 +73,6 @@ public class PresentationService {
|
||||
presentationApplication.sharePresentation(scope.getName(), presentationID, share);
|
||||
}
|
||||
|
||||
public void sendCursorUpdate(Map<String, Object> msg) {
|
||||
IScope scope = Red5.getConnectionLocal().getScope();
|
||||
|
||||
Double xPercent;
|
||||
if (msg.get("xPercent") instanceof Integer) {
|
||||
Integer tempXOffset = (Integer) msg.get("xPercent");
|
||||
xPercent = tempXOffset.doubleValue();
|
||||
} else {
|
||||
xPercent = (Double) msg.get("xPercent");
|
||||
}
|
||||
|
||||
Double yPercent;
|
||||
|
||||
if (msg.get("yPercent") instanceof Integer) {
|
||||
Integer tempYOffset = (Integer) msg.get("yPercent");
|
||||
yPercent = tempYOffset.doubleValue();
|
||||
} else {
|
||||
yPercent = (Double) msg.get("yPercent");
|
||||
}
|
||||
|
||||
presentationApplication.sendCursorUpdate(scope.getName(), xPercent, yPercent);
|
||||
}
|
||||
|
||||
public void resizeAndMoveSlide(Map<String, Object> msg) {
|
||||
Double xOffset;
|
||||
if (msg.get("xOffset") instanceof Integer) {
|
||||
|
@ -100,6 +100,10 @@ public class WhiteboardApplication implements IApplication {
|
||||
red5BBBInGW.sendWhiteboardAnnotation(meetingID, requesterID, shape);
|
||||
}
|
||||
|
||||
public void sendCursorPosition(String meetingID, String requesterID, Double xPercent, Double yPercent) {
|
||||
red5BBBInGW.sendCursorPosition(meetingID, requesterID, xPercent, yPercent);
|
||||
}
|
||||
|
||||
public void clearWhiteboard(String meetingID, String requesterID, String whiteboardId) {
|
||||
red5BBBInGW.clearWhiteboard(meetingID, requesterID, whiteboardId);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import org.bigbluebutton.red5.BigBlueButtonSession;
|
||||
import org.bigbluebutton.red5.Constants;
|
||||
import org.red5.logging.Red5LoggerFactory;
|
||||
import org.red5.server.api.Red5;
|
||||
import org.red5.server.api.scope.IScope;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class WhiteboardService {
|
||||
@ -47,19 +48,6 @@ public class WhiteboardService {
|
||||
return false;
|
||||
}
|
||||
public void sendAnnotation(Map<String, Object> annotation) {
|
||||
// for (Map.Entry<String, Object> entry : annotation.entrySet()) {
|
||||
// String key = entry.getKey();
|
||||
// Object value = entry.getValue();
|
||||
|
||||
// if (key.equals("points")) {
|
||||
// String points = "points=[";
|
||||
// ArrayList<Double> v = (ArrayList<Double>) value;
|
||||
// log.debug(points + pointsToString(v) + "]");
|
||||
// } else {
|
||||
// log.debug(key + "=[" + value + "]");
|
||||
// }
|
||||
// }
|
||||
|
||||
String meetingID = getMeetingId();
|
||||
String requesterID = getBbbSession().getInternalUserID();
|
||||
|
||||
@ -68,18 +56,29 @@ public class WhiteboardService {
|
||||
}
|
||||
}
|
||||
|
||||
/*private String pointsToString(ArrayList<Double> points){
|
||||
String datapoints = "";
|
||||
for (Double i : points) {
|
||||
datapoints += i + ",";
|
||||
public void sendCursorPosition(Map<String, Object> msg) {
|
||||
String meetingID = getMeetingId();
|
||||
String requesterID = getBbbSession().getInternalUserID();
|
||||
|
||||
Double xPercent;
|
||||
if (msg.get("xPercent") instanceof Integer) {
|
||||
Integer tempXOffset = (Integer) msg.get("xPercent");
|
||||
xPercent = tempXOffset.doubleValue();
|
||||
} else {
|
||||
xPercent = (Double) msg.get("xPercent");
|
||||
}
|
||||
// Trim the trailing comma
|
||||
// log.debug("Data Point = " + datapoints);
|
||||
return datapoints.substring(0, datapoints.length() - 1);
|
||||
|
||||
// application.sendShape(shape, type, color, thickness, fill, fillColor, transparency, id, status);
|
||||
Double yPercent;
|
||||
|
||||
}*/
|
||||
if (msg.get("yPercent") instanceof Integer) {
|
||||
Integer tempYOffset = (Integer) msg.get("yPercent");
|
||||
yPercent = tempYOffset.doubleValue();
|
||||
} else {
|
||||
yPercent = (Double) msg.get("yPercent");
|
||||
}
|
||||
|
||||
application.sendCursorPosition(meetingID, requesterID, xPercent, yPercent);
|
||||
}
|
||||
|
||||
public void requestAnnotationHistory(Map<String, Object> message) {
|
||||
log.info("WhiteboardApplication - requestAnnotationHistory");
|
||||
|
10
bigbluebutton-client/src/org/bigbluebutton/modules/present/business/PresentProxy.as
Normal file → Executable file
10
bigbluebutton-client/src/org/bigbluebutton/modules/present/business/PresentProxy.as
Normal file → Executable file
@ -229,15 +229,5 @@ package org.bigbluebutton.modules.present.business
|
||||
public function zoomSlide(e:PresenterCommands):void{
|
||||
sender.move(e.xOffset, e.yOffset, e.slideToCanvasWidthRatio, e.slideToCanvasHeightRatio);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the presenter cursor within the presentation window
|
||||
* @param e
|
||||
*
|
||||
*/
|
||||
public function sendCursorUpdate(e:PresenterCommands):void{
|
||||
sender.sendCursorUpdate(e.xPercent, e.yPercent);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -34,7 +34,6 @@ package org.bigbluebutton.modules.present.events
|
||||
public static const RESET_ZOOM:String = "RESTORE_ZOOM";
|
||||
public static const MOVE:String = "MOVE_COMMAND";
|
||||
public static const SHARE_PRESENTATION_COMMAND:String = "SHARE_PRESENTATION_COMMAND";
|
||||
public static const SEND_CURSOR_UPDATE:String = "SEND_CURSOR_UPDATE";
|
||||
|
||||
//Parameter for the slide navigation events
|
||||
public var slideNumber:Number;
|
||||
@ -45,10 +44,6 @@ package org.bigbluebutton.modules.present.events
|
||||
//Parameters for the resize event
|
||||
public var newSizeInPercent:Number;
|
||||
|
||||
//Parameters for the cursor event
|
||||
public var xPercent:Number;
|
||||
public var yPercent:Number;
|
||||
|
||||
//Parameters for the move event
|
||||
public var xOffset:Number;
|
||||
public var yOffset:Number;
|
||||
|
@ -109,10 +109,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
<MethodInvoker generator="{PresentProxy}" method="handleGetListOfPresentationsRequest" />
|
||||
</EventHandlers>
|
||||
|
||||
<EventHandlers type="{PresenterCommands.SEND_CURSOR_UPDATE}" >
|
||||
<MethodInvoker generator="{PresentProxy}" method="sendCursorUpdate" arguments="{event}" />
|
||||
</EventHandlers>
|
||||
|
||||
<EventHandlers type="{PresenterCommands.RESIZE}" >
|
||||
<MethodInvoker generator="{PresentProxy}" method="resizeSlide" arguments="{event}" />
|
||||
</EventHandlers>
|
||||
|
@ -5,7 +5,6 @@ package org.bigbluebutton.modules.present.services
|
||||
import mx.collections.ArrayCollection;
|
||||
|
||||
import org.bigbluebutton.modules.present.commands.ChangePageCommand;
|
||||
import org.bigbluebutton.modules.present.events.CursorEvent;
|
||||
import org.bigbluebutton.modules.present.events.PageChangedEvent;
|
||||
import org.bigbluebutton.modules.present.events.PresentationChangedEvent;
|
||||
import org.bigbluebutton.modules.present.events.RemovePresentationEvent;
|
||||
@ -35,13 +34,6 @@ package org.bigbluebutton.modules.present.services
|
||||
dispatcher = new Dispatcher();
|
||||
}
|
||||
|
||||
public function cursorMoved(x: Number, y: Number):void {
|
||||
var e:CursorEvent = new CursorEvent(CursorEvent.UPDATE_CURSOR);
|
||||
e.xPercent = x;
|
||||
e.yPercent = y;
|
||||
dispatcher.dispatchEvent(e);
|
||||
}
|
||||
|
||||
public function pageChanged(page: PageVO):void {
|
||||
var np: Page = model.getPage(page.id);
|
||||
if (np != null) {
|
||||
|
@ -60,9 +60,6 @@ package org.bigbluebutton.modules.present.services.messaging
|
||||
//LOGGER.info("Presentation: received message " + messageName);
|
||||
|
||||
switch (messageName) {
|
||||
case "PresentationCursorUpdateCommand":
|
||||
handlePresentationCursorUpdateCommand(message);
|
||||
break;
|
||||
case "goToSlideCallback":
|
||||
handleGotoSlideCallback(message);
|
||||
break;
|
||||
@ -101,14 +98,6 @@ package org.bigbluebutton.modules.present.services.messaging
|
||||
|
||||
}
|
||||
|
||||
private function handlePresentationCursorUpdateCommand(msg:Object):void {
|
||||
// trace(LOG + "*** handlePresentationCursorUpdateCommand " + msg.msg + " **** \n");
|
||||
var map:Object = JSON.parse(msg.msg);
|
||||
if (map.hasOwnProperty("xPercent") && map.hasOwnProperty("yPercent")) {
|
||||
service.cursorMoved(map.xPercent, map.yPercent);
|
||||
}
|
||||
}
|
||||
|
||||
private function handleGotoSlideCallback(msg:Object) : void {
|
||||
var map:Object = JSON.parse(msg.msg);
|
||||
|
||||
|
@ -27,29 +27,6 @@ package org.bigbluebutton.modules.present.services.messaging
|
||||
|
||||
private static const LOGGER:ILogger = getClassLogger(MessageSender);
|
||||
|
||||
/**
|
||||
* Send an event to the server to update the presenter's cursor view on the client
|
||||
* @param xPercent
|
||||
* @param yPercent
|
||||
*
|
||||
*/
|
||||
public function sendCursorUpdate(xPercent:Number, yPercent:Number):void{
|
||||
var message:Object = new Object();
|
||||
message["xPercent"] = xPercent;
|
||||
message["yPercent"] = yPercent;
|
||||
|
||||
var _nc:ConnectionManager = BBB.initConnectionManager();
|
||||
_nc.sendMessage("presentation.sendCursorUpdate",
|
||||
function(result:String):void { // On successful result
|
||||
//LOGGER.debug(result);
|
||||
},
|
||||
function(status:String):void { // status - On error occurred
|
||||
LOGGER.error(status);
|
||||
},
|
||||
message
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an event to the server to update the clients with the new slide position
|
||||
* @param slideXPosition
|
||||
|
@ -29,14 +29,13 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
creationComplete="onCreationComplete()"
|
||||
verticalScrollPolicy="off"
|
||||
horizontalScrollPolicy="off"
|
||||
rollOut="hideCursor()" styleName="presentationSlideViewStyle"
|
||||
styleName="presentationSlideViewStyle"
|
||||
xmlns:views="org.bigbluebutton.modules.present.views.*">
|
||||
|
||||
<mate:Listener type="{PageChangedEvent.PRESENTATION_PAGE_CHANGED_EVENT}" method="handlePageChangedEvent" />
|
||||
<mate:Listener type="{PageLoadedEvent.PAGE_LOADED_EVENT}" method="handlePageLoadedEvent" />
|
||||
<mate:Listener type="{MadePresenterEvent.SWITCH_TO_PRESENTER_MODE}" method="handleSwitchToPresenterEvent" />
|
||||
<mate:Listener type="{MadePresenterEvent.SWITCH_TO_VIEWER_MODE}" method="handleSwitchToViewerEvent" />
|
||||
<mate:Listener type="{CursorEvent.UPDATE_CURSOR}" method="handleUpdateCursorEvent" />
|
||||
<mate:Listener type="{ShortcutEvent.FOCUS_SLIDE}" method="focusSlide" />
|
||||
<mx:Script>
|
||||
<![CDATA[
|
||||
@ -46,7 +45,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
import mx.collections.Sort;
|
||||
import mx.collections.SortField;
|
||||
import mx.containers.Canvas;
|
||||
import mx.managers.CursorManager;
|
||||
|
||||
import org.as3commons.logging.api.ILogger;
|
||||
import org.as3commons.logging.api.getClassLogger;
|
||||
@ -55,7 +53,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
import org.bigbluebutton.main.events.MadePresenterEvent;
|
||||
import org.bigbluebutton.main.events.ShortcutEvent;
|
||||
import org.bigbluebutton.modules.present.commands.GoToPageCommand;
|
||||
import org.bigbluebutton.modules.present.events.CursorEvent;
|
||||
import org.bigbluebutton.modules.present.events.DisplaySlideEvent;
|
||||
import org.bigbluebutton.modules.present.events.PageChangedEvent;
|
||||
import org.bigbluebutton.modules.present.events.PageLoadedEvent;
|
||||
@ -74,7 +71,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
public static const ZOOM_STEP:int = 5;
|
||||
public static const THUMBNAILS_CLOSED:String = "ThumbnailsClosed";
|
||||
|
||||
private var cursor:Shape;
|
||||
private var whiteboardCanvas:WhiteboardCanvas;
|
||||
|
||||
private var dispatcher:Dispatcher = new Dispatcher();
|
||||
@ -84,21 +80,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
private var pageCache:ArrayCollection = new ArrayCollection();
|
||||
|
||||
// Send update of mouse location to other users.
|
||||
private var _sendCurrentMouseLocTimer:Timer = new Timer(100);
|
||||
private var _lastMouseXPosition:Number = 0;
|
||||
private var _lastMouseYPosition:Number = 0;
|
||||
|
||||
private function onCreationComplete():void {
|
||||
slideLoader.width = this.width;
|
||||
slideLoader.height = this.height;
|
||||
|
||||
cursor = new Shape();
|
||||
cursor.graphics.lineStyle(6, 0xFF0000, 0.6);
|
||||
cursor.graphics.drawCircle(0,0,2.5);
|
||||
this.rawChildren.addChild(cursor);
|
||||
cursor.visible = false;
|
||||
|
||||
this.setChildIndex(thumbnailView, this.numChildren - 1);
|
||||
|
||||
/*
|
||||
@ -340,8 +325,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
private function becomeViewer():void {
|
||||
removeEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheelZoomEvent);
|
||||
this.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
|
||||
_sendCurrentMouseLocTimer.stop();
|
||||
_sendCurrentMouseLocTimer.removeEventListener(TimerEvent.TIMER, mouseCursorUpdateTimerListener);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -361,8 +344,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheelZoomEvent);
|
||||
this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
|
||||
_sendCurrentMouseLocTimer.addEventListener(TimerEvent.TIMER, mouseCursorUpdateTimerListener);
|
||||
_sendCurrentMouseLocTimer.start();
|
||||
notifyOthersOfZoomEvent();
|
||||
}
|
||||
|
||||
@ -373,53 +354,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
becomePresenter();
|
||||
}
|
||||
|
||||
|
||||
public function mouseCursorUpdateTimerListener(e:TimerEvent):void{
|
||||
if (noSlideContentLoaded()) return;
|
||||
notifyOthersOfPresentersCursorPosition(this.mouseX, this.mouseY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast to other participants the location fo the mouse cursor.
|
||||
*/
|
||||
private function notifyOthersOfPresentersCursorPosition(cursorXPosition:int, cursorYPosition:int):void {
|
||||
// Only update the other users if the mouse moved a certain delta
|
||||
if ( (Math.abs(cursorXPosition - _lastMouseXPosition) < 0.1)
|
||||
&& (Math.abs(cursorYPosition - _lastMouseYPosition) < 0.1) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cursorXPosition > this.width || cursorXPosition < 1
|
||||
|| cursorYPosition > this.height || cursorYPosition < 1) {
|
||||
// LogUtil.debug("Cursor outside the window...not sending [" + cursorXPosition + "," + cursorYPosition + "]");
|
||||
return;
|
||||
}
|
||||
|
||||
_lastMouseXPosition = cursorXPosition;
|
||||
_lastMouseYPosition = cursorYPosition;
|
||||
|
||||
var command:PresenterCommands = new PresenterCommands(PresenterCommands.SEND_CURSOR_UPDATE);
|
||||
command.xPercent = cursorXPosition / this.width;
|
||||
command.yPercent = cursorYPosition / this.height;
|
||||
dispatchEvent(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle notification from presenter about the location of the mouse cursor.
|
||||
*/
|
||||
private function handleUpdateCursorEvent(e:CursorEvent):void{
|
||||
if (noSlideContentLoaded()) return;
|
||||
|
||||
cursor.x = e.xPercent * this.width;
|
||||
cursor.y = e.yPercent * this.height;
|
||||
|
||||
if (isCursorOutsideWindow(e)) {
|
||||
hideCursor()
|
||||
} else {
|
||||
showCursor();
|
||||
}
|
||||
}
|
||||
|
||||
private function noSlideContentLoaded():Boolean {
|
||||
return slideLoader.content == null
|
||||
}
|
||||
@ -444,20 +378,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
dispatcher.dispatchEvent(dispEvent);
|
||||
}
|
||||
|
||||
private function isCursorOutsideWindow(e:CursorEvent):Boolean {
|
||||
return (e.xPercent > 1 && e.yPercent > 1)
|
||||
|| (cursor.x > this.width || cursor.x < 1
|
||||
|| cursor.y > this.height || cursor.y < 1);
|
||||
}
|
||||
|
||||
private function showCursor():void {
|
||||
cursor.visible = true;
|
||||
}
|
||||
|
||||
private function hideCursor():void{
|
||||
cursor.visible = false;
|
||||
}
|
||||
|
||||
public function acceptOverlayCanvas(overlay:WhiteboardCanvas):void{
|
||||
whiteboardCanvas = overlay;
|
||||
// add the canvas below the thumbnails
|
||||
|
@ -23,6 +23,7 @@ package org.bigbluebutton.modules.whiteboard
|
||||
import flash.events.FocusEvent;
|
||||
import flash.events.KeyboardEvent;
|
||||
import flash.ui.Keyboard;
|
||||
import flash.utils.Dictionary;
|
||||
|
||||
import org.as3commons.logging.api.ILogger;
|
||||
import org.as3commons.logging.api.getClassLogger;
|
||||
@ -42,6 +43,7 @@ package org.bigbluebutton.modules.whiteboard
|
||||
import org.bigbluebutton.modules.whiteboard.models.WhiteboardModel;
|
||||
import org.bigbluebutton.modules.whiteboard.views.TextUpdateListener;
|
||||
import org.bigbluebutton.modules.whiteboard.views.WhiteboardCanvas;
|
||||
import org.bigbluebutton.modules.whiteboard.views.WhiteboardCursor;
|
||||
|
||||
/**
|
||||
* Class to handle displaying of received annotations from the server.
|
||||
@ -52,11 +54,13 @@ package org.bigbluebutton.modules.whiteboard
|
||||
private var whiteboardModel:WhiteboardModel;
|
||||
private var wbCanvas:WhiteboardCanvas;
|
||||
private var _annotationsList:Array = new Array();
|
||||
private var _cursors:Object = new Object();
|
||||
private var shapeFactory:ShapeFactory = new ShapeFactory();
|
||||
private var textUpdateListener:TextUpdateListener = new TextUpdateListener();
|
||||
|
||||
private var width:Number;
|
||||
private var height:Number;
|
||||
private var presenterId:String;
|
||||
|
||||
public function setDependencies(whiteboardCanvas:WhiteboardCanvas, whiteboardModel:WhiteboardModel):void {
|
||||
wbCanvas = whiteboardCanvas;
|
||||
@ -210,6 +214,32 @@ package org.bigbluebutton.modules.whiteboard
|
||||
}
|
||||
}
|
||||
|
||||
public function drawCursor(userId:String, xPercent:Number, yPercent:Number):void {
|
||||
if (!_cursors.hasOwnProperty(userId)) {
|
||||
var newCursor:WhiteboardCursor = new WhiteboardCursor(userId, xPercent, yPercent, shapeFactory.parentWidth, shapeFactory.parentHeight, presenterId == userId);
|
||||
wbCanvas.addCursor(newCursor);
|
||||
|
||||
_cursors[userId] = newCursor;
|
||||
} else {
|
||||
(_cursors[userId] as WhiteboardCursor).updatePosition(xPercent, yPercent);
|
||||
}
|
||||
}
|
||||
|
||||
public function presenterChange(amIPresenter:Boolean, presenterId:String):void {
|
||||
this.presenterId = presenterId;
|
||||
|
||||
for(var j:String in _cursors) {
|
||||
(_cursors[j] as WhiteboardCursor).updatePresenter(j == presenterId);
|
||||
}
|
||||
}
|
||||
|
||||
public function userLeft(userId:String):void {
|
||||
if (_cursors.hasOwnProperty(userId)) {
|
||||
wbCanvas.removeCursorChild(_cursors[userId]);
|
||||
delete _cursors[userId];
|
||||
}
|
||||
}
|
||||
|
||||
public function zoomCanvas(width:Number, height:Number):void{
|
||||
shapeFactory.setParentDim(width, height);
|
||||
this.width = width;
|
||||
@ -218,6 +248,10 @@ package org.bigbluebutton.modules.whiteboard
|
||||
for (var i:int = 0; i < this._annotationsList.length; i++){
|
||||
redrawGraphic(this._annotationsList[i] as GraphicObject, i);
|
||||
}
|
||||
|
||||
for(var j:String in _cursors) {
|
||||
(_cursors[j] as WhiteboardCursor).updateParentSize(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
private function redrawGraphic(gobj:GraphicObject, objIndex:int):void {
|
||||
|
@ -26,6 +26,7 @@ package org.bigbluebutton.modules.whiteboard
|
||||
import org.bigbluebutton.modules.whiteboard.business.shapes.ShapeFactory;
|
||||
import org.bigbluebutton.modules.whiteboard.models.WhiteboardModel;
|
||||
import org.bigbluebutton.modules.whiteboard.views.AnnotationIDGenerator;
|
||||
import org.bigbluebutton.modules.whiteboard.views.CursorPositionListener;
|
||||
import org.bigbluebutton.modules.whiteboard.views.IDrawListener;
|
||||
import org.bigbluebutton.modules.whiteboard.views.PencilDrawListener;
|
||||
import org.bigbluebutton.modules.whiteboard.views.ShapeDrawListener;
|
||||
@ -39,32 +40,23 @@ package org.bigbluebutton.modules.whiteboard
|
||||
public class WhiteboardCanvasModel {
|
||||
private var _wbCanvas:WhiteboardCanvas;
|
||||
private var drawListeners:Array = new Array();
|
||||
private var cursorPositionListener:CursorPositionListener;
|
||||
private var wbTool:WhiteboardTool = new WhiteboardTool();
|
||||
private var shapeFactory:ShapeFactory = new ShapeFactory();
|
||||
private var idGenerator:AnnotationIDGenerator = new AnnotationIDGenerator();
|
||||
|
||||
/* represents the max number of 'points' enumerated in 'segment' before
|
||||
sending an update to server. Used to prevent spamming red5 with unnecessary packets */
|
||||
private var sendShapeFrequency:uint = 30;
|
||||
|
||||
/* same as above, except a faster interval may be desirable when erasing, for aesthetics */
|
||||
private var sendEraserFrequency:uint = 20;
|
||||
|
||||
private var width:Number;
|
||||
private var height:Number;
|
||||
|
||||
public function setDependencies(canvas:WhiteboardCanvas, displayModel:WhiteboardCanvasDisplayModel):void {
|
||||
public function setDependencies(canvas:WhiteboardCanvas):void {
|
||||
_wbCanvas = canvas;
|
||||
|
||||
drawListeners.push(new PencilDrawListener(idGenerator, _wbCanvas, shapeFactory));
|
||||
drawListeners.push(new ShapeDrawListener(idGenerator, _wbCanvas, shapeFactory));
|
||||
drawListeners.push(new TextDrawListener(idGenerator, _wbCanvas, shapeFactory));
|
||||
|
||||
cursorPositionListener = new CursorPositionListener(_wbCanvas, shapeFactory);
|
||||
}
|
||||
|
||||
public function zoomCanvas(width:Number, height:Number):void {
|
||||
shapeFactory.setParentDim(width, height);
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public function changeFontStyle(font:String):void {
|
||||
@ -113,6 +105,14 @@ package org.bigbluebutton.modules.whiteboard
|
||||
wbTool.thickness = thickness;
|
||||
}
|
||||
|
||||
public function presenterChange(amIPresenter:Boolean, presenterId:String):void {
|
||||
cursorPositionListener.presenterChange(amIPresenter);
|
||||
}
|
||||
|
||||
public function multiUserChange(multiUser:Boolean):void {
|
||||
cursorPositionListener.multiUserChange(multiUser);
|
||||
}
|
||||
|
||||
/** Helper method to test whether this user is the presenter */
|
||||
private function get isPresenter():Boolean {
|
||||
return UserManager.getInstance().getConference().amIPresenter;
|
||||
|
@ -16,19 +16,18 @@
|
||||
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
package org.bigbluebutton.modules.present.events
|
||||
{
|
||||
package org.bigbluebutton.modules.whiteboard.events {
|
||||
import flash.events.Event;
|
||||
|
||||
public class CursorEvent extends Event
|
||||
{
|
||||
public static const UPDATE_CURSOR:String = "UPDATE_CURSOR";
|
||||
public class WhiteboardCursorEvent extends Event {
|
||||
public static const SEND_CURSOR_POSITION:String = "SEND_CURSOR_POSITION";
|
||||
public static const RECEIVED_CURSOR_POSITION:String = "RECEIVE_CURSOR_POSITION";
|
||||
|
||||
public var xPercent:Number;
|
||||
public var yPercent:Number;
|
||||
public var userId:String;
|
||||
|
||||
public function CursorEvent(type:String)
|
||||
{
|
||||
public function WhiteboardCursorEvent(type:String) {
|
||||
super(type, true, false);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
import org.bigbluebutton.modules.whiteboard.events.StartWhiteboardModuleEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardAccessEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardCursorEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardDrawEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardUpdateReceived;
|
||||
import org.bigbluebutton.modules.whiteboard.managers.WhiteboardManager;
|
||||
@ -80,6 +81,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
<MethodInvoker generator="{WhiteboardService}" method="undoGraphic" arguments="{event}" />
|
||||
</EventHandlers>
|
||||
|
||||
<EventHandlers type="{WhiteboardCursorEvent.SEND_CURSOR_POSITION}" >
|
||||
<MethodInvoker generator="{WhiteboardService}" method="sendCursorPosition" arguments="{event}" />
|
||||
</EventHandlers>
|
||||
|
||||
<EventHandlers type="{GetWhiteboardShapesCommand.GET_SHAPES}" >
|
||||
<MethodInvoker generator="{WhiteboardService}" method="getAnnotationHistory" arguments="{event}" />
|
||||
</EventHandlers>
|
||||
|
@ -31,6 +31,7 @@ package org.bigbluebutton.modules.whiteboard.models
|
||||
import org.bigbluebutton.modules.whiteboard.business.shapes.DrawObject;
|
||||
import org.bigbluebutton.modules.whiteboard.commands.GetWhiteboardShapesCommand;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardAccessEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardCursorEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardDrawEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardUpdateReceived;
|
||||
|
||||
@ -159,5 +160,13 @@ package org.bigbluebutton.modules.whiteboard.models
|
||||
return _multiUser;
|
||||
}
|
||||
|
||||
public function updateCursorPosition(userId:String, xPercent:Number, yPercent:Number):void {
|
||||
var event:WhiteboardCursorEvent = new WhiteboardCursorEvent(WhiteboardCursorEvent.RECEIVED_CURSOR_POSITION);
|
||||
event.userId = userId;
|
||||
event.xPercent = xPercent;
|
||||
event.yPercent = yPercent;
|
||||
dispatchEvent(event);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -59,6 +59,9 @@ package org.bigbluebutton.modules.whiteboard.services
|
||||
case "WhiteboardUndoCommand":
|
||||
handleUndoCommand(message);
|
||||
break;
|
||||
case "WhiteboardCursorPositionUpdatedCommand":
|
||||
handleCursorPositionUpdatedCommand(message);
|
||||
break;
|
||||
default:
|
||||
// LogUtil.warn("Cannot handle message [" + messageName + "]");
|
||||
}
|
||||
@ -124,5 +127,11 @@ package org.bigbluebutton.modules.whiteboard.services
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function handleCursorPositionUpdatedCommand(message:Object):void {
|
||||
var map:Object = JSON.parse(message.msg);
|
||||
|
||||
whiteboardModel.updateCursorPosition(map.requesterId, map.xPercent, map.yPercent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,5 +143,28 @@ package org.bigbluebutton.modules.whiteboard.services
|
||||
e.annotation.annotation
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an event to the server to update the user's cursor position
|
||||
* @param xPercent
|
||||
* @param yPercent
|
||||
*
|
||||
*/
|
||||
public function sendCursorPosition(xPercent:Number, yPercent:Number):void {
|
||||
var message:Object = new Object();
|
||||
message["xPercent"] = xPercent;
|
||||
message["yPercent"] = yPercent;
|
||||
|
||||
var _nc:ConnectionManager = BBB.initConnectionManager();
|
||||
_nc.sendMessage("whiteboard.sendCursorPosition",
|
||||
function(result:String):void { // On successful result
|
||||
//LOGGER.debug(result);
|
||||
},
|
||||
function(status:String):void { // status - On error occurred
|
||||
LOGGER.error(status);
|
||||
},
|
||||
message
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,9 @@ package org.bigbluebutton.modules.whiteboard.services
|
||||
import org.as3commons.logging.api.ILogger;
|
||||
import org.as3commons.logging.api.getClassLogger;
|
||||
import org.bigbluebutton.modules.whiteboard.commands.GetWhiteboardShapesCommand;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardDrawEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardAccessEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardCursorEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardDrawEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.models.WhiteboardModel;
|
||||
|
||||
public class WhiteboardService
|
||||
@ -66,6 +67,8 @@ package org.bigbluebutton.modules.whiteboard.services
|
||||
sender.sendShape(e);
|
||||
}
|
||||
|
||||
|
||||
public function sendCursorPosition(e:WhiteboardCursorEvent):void {
|
||||
sender.sendCursorPosition(e.xPercent, e.yPercent);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package org.bigbluebutton.modules.whiteboard.views {
|
||||
import flash.events.TimerEvent;
|
||||
import flash.geom.Point;
|
||||
import flash.utils.Timer;
|
||||
|
||||
import org.bigbluebutton.modules.whiteboard.business.shapes.ShapeFactory;
|
||||
|
||||
public class CursorPositionListener {
|
||||
|
||||
private var _wbCanvas:WhiteboardCanvas;
|
||||
private var _shapeFactory:ShapeFactory;
|
||||
|
||||
private var _timer:Timer;
|
||||
private var _lastXPosition:Number;
|
||||
private var _lastYPosition:Number;
|
||||
|
||||
private var _amIPresenter:Boolean;
|
||||
private var _multiUser:Boolean;
|
||||
|
||||
public function CursorPositionListener(wbCanvas:WhiteboardCanvas, shapeFactory:ShapeFactory) {
|
||||
_wbCanvas = wbCanvas;
|
||||
_shapeFactory = shapeFactory;
|
||||
|
||||
_lastXPosition = -1;
|
||||
_lastYPosition = 1;
|
||||
|
||||
_timer = new Timer(100);
|
||||
_timer.addEventListener(TimerEvent.TIMER, onTimerInterval);
|
||||
}
|
||||
|
||||
public function presenterChange(amIPresenter:Boolean):void {
|
||||
_amIPresenter = amIPresenter;
|
||||
verifyTimerState();
|
||||
}
|
||||
|
||||
public function multiUserChange(multiUser:Boolean):void {
|
||||
_multiUser = multiUser;
|
||||
verifyTimerState();
|
||||
}
|
||||
|
||||
private function verifyTimerState():void {
|
||||
if (_amIPresenter || _multiUser) {
|
||||
startTimer();
|
||||
} else {
|
||||
stopTimer();
|
||||
}
|
||||
}
|
||||
|
||||
private function startTimer():void {
|
||||
if (!_timer.running) {
|
||||
_timer.start();
|
||||
}
|
||||
}
|
||||
|
||||
private function stopTimer():void {
|
||||
if (_timer.running) {
|
||||
_timer.stop();
|
||||
checkMousePosition(-1, -1)
|
||||
}
|
||||
}
|
||||
|
||||
private function onTimerInterval(e:TimerEvent):void {
|
||||
checkMousePosition(_wbCanvas.mouseX, _wbCanvas.mouseY);
|
||||
}
|
||||
|
||||
private function checkMousePosition(x:Number, y:Number):void {
|
||||
// check if mouse position is within bounds
|
||||
if (isXYOutsideCanvas(x, y)){
|
||||
x = -1;
|
||||
y = -1;
|
||||
}
|
||||
|
||||
if (x != _lastXPosition || y != _lastYPosition) {
|
||||
_lastXPosition = x;
|
||||
_lastYPosition = y;
|
||||
|
||||
var np:Point = _shapeFactory.normalizePoint(x, y);
|
||||
|
||||
_wbCanvas.sendCursorPositionToServer(np.x, np.y);
|
||||
}
|
||||
}
|
||||
|
||||
private function isXYOutsideCanvas(x:Number, y:Number):Boolean {
|
||||
return (x < 0 || y < 0 || x > _wbCanvas.width || y > _wbCanvas.height);
|
||||
}
|
||||
}
|
||||
}
|
@ -25,12 +25,15 @@ package org.bigbluebutton.modules.whiteboard.views {
|
||||
import flash.display.DisplayObject;
|
||||
import flash.events.Event;
|
||||
import flash.events.MouseEvent;
|
||||
import flash.geom.Point;
|
||||
|
||||
import mx.containers.Canvas;
|
||||
import mx.managers.CursorManager;
|
||||
|
||||
import org.bigbluebutton.common.Images;
|
||||
import org.bigbluebutton.core.UsersUtil;
|
||||
import org.bigbluebutton.main.events.MadePresenterEvent;
|
||||
import org.bigbluebutton.main.events.UserLeftEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.WhiteboardCanvasDisplayModel;
|
||||
import org.bigbluebutton.modules.whiteboard.WhiteboardCanvasModel;
|
||||
import org.bigbluebutton.modules.whiteboard.business.shapes.DrawObject;
|
||||
@ -39,6 +42,7 @@ package org.bigbluebutton.modules.whiteboard.views {
|
||||
import org.bigbluebutton.modules.whiteboard.commands.GetWhiteboardShapesCommand;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardAccessEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardCursorEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardDrawEvent;
|
||||
import org.bigbluebutton.modules.whiteboard.events.WhiteboardUpdateReceived;
|
||||
import org.bigbluebutton.modules.whiteboard.models.Annotation;
|
||||
@ -52,8 +56,9 @@ package org.bigbluebutton.modules.whiteboard.views {
|
||||
private var textToolbar:WhiteboardTextToolbar;
|
||||
|
||||
private var graphicObjectHolder:Canvas = new Canvas();
|
||||
private var images:Images = new Images();
|
||||
private var cursorObjectHolder:Canvas = new Canvas();
|
||||
|
||||
private var images:Images = new Images();
|
||||
[Bindable] private var pencil_icon:Class = images.pencil_icon;
|
||||
[Bindable] private var rectangle_icon:Class = images.square_icon;
|
||||
[Bindable] private var triangle_icon:Class = images.triangle_icon;
|
||||
@ -64,12 +69,14 @@ package org.bigbluebutton.modules.whiteboard.views {
|
||||
private var whiteboardEnabled:Boolean = false;
|
||||
private var currentWhiteboardId:String;
|
||||
|
||||
private var dispatcher:Dispatcher = new Dispatcher();
|
||||
|
||||
public function WhiteboardCanvas(wbModel:WhiteboardModel):void {
|
||||
canvasModel = new WhiteboardCanvasModel();
|
||||
canvasDisplayModel = new WhiteboardCanvasDisplayModel();
|
||||
|
||||
//set up model cross dependencies
|
||||
canvasModel.setDependencies(this, canvasDisplayModel);
|
||||
canvasModel.setDependencies(this);
|
||||
canvasDisplayModel.setDependencies(this, wbModel);
|
||||
|
||||
whiteboardToolbar = new WhiteboardToolbar();
|
||||
@ -87,17 +94,36 @@ package org.bigbluebutton.modules.whiteboard.views {
|
||||
graphicObjectHolder.clipContent = true;
|
||||
graphicObjectHolder.tabFocusEnabled = false;
|
||||
|
||||
addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
|
||||
addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
|
||||
//create the cursor display container
|
||||
this.addChild(cursorObjectHolder);
|
||||
cursorObjectHolder.x = 0;
|
||||
cursorObjectHolder.y = 0;
|
||||
cursorObjectHolder.clipContent = true;
|
||||
cursorObjectHolder.tabFocusEnabled = false;
|
||||
|
||||
wbModel.addEventListener(WhiteboardUpdateReceived.NEW_ANNOTATION, onNewAnnotationEvent);
|
||||
wbModel.addEventListener(WhiteboardUpdateReceived.RECEIVED_ANNOTATION_HISTORY, onReceivedAnnotationsHistory);
|
||||
wbModel.addEventListener(WhiteboardUpdateReceived.CLEAR_ANNOTATIONS, onClearAnnotations);
|
||||
wbModel.addEventListener(WhiteboardUpdateReceived.UNDO_ANNOTATION, onUndoAnnotation);
|
||||
wbModel.addEventListener(WhiteboardAccessEvent.MODIFIED_WHITEBOARD_ACCESS, onModifiedAccess);
|
||||
wbModel.addEventListener(WhiteboardCursorEvent.RECEIVED_CURSOR_POSITION, onReceivedCursorPosition);
|
||||
|
||||
whiteboardToolbar.addEventListener(WhiteboardButtonEvent.ENABLE_WHITEBOARD, onEnableWhiteboardEvent);
|
||||
whiteboardToolbar.addEventListener(WhiteboardButtonEvent.DISABLE_WHITEBOARD, onDisableWhiteboardEvent);
|
||||
|
||||
var stpl:Listener = new Listener();
|
||||
stpl.type = MadePresenterEvent.SWITCH_TO_PRESENTER_MODE;
|
||||
stpl.method = onSwitchToPresenterEvent;
|
||||
|
||||
var stvl:Listener = new Listener();
|
||||
stvl.type = MadePresenterEvent.SWITCH_TO_VIEWER_MODE;
|
||||
stvl.method = onSwitchToViewerEvent;
|
||||
|
||||
presenterChange(UsersUtil.amIPresenter(), UsersUtil.getPresenterUserID());
|
||||
|
||||
var ull:Listener = new Listener();
|
||||
ull.type = UserLeftEvent.LEFT;
|
||||
ull.method = onUserLeftEvent;
|
||||
}
|
||||
|
||||
public function attachToReceivingObject(ro:IWhiteboardReceiver):void {
|
||||
@ -107,14 +133,19 @@ package org.bigbluebutton.modules.whiteboard.views {
|
||||
|
||||
private function registerForMouseEvents():void {
|
||||
addEventListener(MouseEvent.MOUSE_DOWN, doMouseDown);
|
||||
addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
|
||||
addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
|
||||
}
|
||||
|
||||
private function unregisterForMouseEvents():void {
|
||||
removeEventListener(MouseEvent.MOUSE_DOWN, doMouseDown);
|
||||
removeEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
|
||||
removeEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
|
||||
}
|
||||
|
||||
private function doMouseUp(event:MouseEvent):void {
|
||||
canvasModel.doMouseUp(Math.min(Math.max(parent.mouseX, 0), parent.width) - this.x, Math.min(Math.max(parent.mouseY, 0), parent.height) - this.y);
|
||||
var mousePoint:Point = getMouseXY();
|
||||
canvasModel.doMouseUp(mousePoint.x, mousePoint.y);
|
||||
|
||||
stage.removeEventListener(MouseEvent.MOUSE_UP, doMouseUp);
|
||||
stage.removeEventListener(MouseEvent.MOUSE_MOVE, doMouseMove);
|
||||
@ -130,7 +161,8 @@ package org.bigbluebutton.modules.whiteboard.views {
|
||||
}
|
||||
|
||||
private function doMouseMove(event:MouseEvent):void {
|
||||
canvasModel.doMouseMove(Math.min(Math.max(parent.mouseX, 0), parent.width-1) - this.x, Math.min(Math.max(parent.mouseY, 0), parent.height-1) - this.y);
|
||||
var mousePoint:Point = getMouseXY();
|
||||
canvasModel.doMouseMove(mousePoint.x, mousePoint.y);
|
||||
}
|
||||
|
||||
public function changeColor(e:Event):void {
|
||||
@ -145,21 +177,25 @@ package org.bigbluebutton.modules.whiteboard.views {
|
||||
// LogUtil.debug("DISPATCHING SEND sendGraphicToServer [" + type + "]");
|
||||
var event:WhiteboardDrawEvent = new WhiteboardDrawEvent(WhiteboardDrawEvent.SEND_SHAPE);
|
||||
event.annotation = gobj;
|
||||
var dispatcher:Dispatcher = new Dispatcher();
|
||||
dispatcher.dispatchEvent(event);
|
||||
}
|
||||
|
||||
public function sendUndoToServer():void {
|
||||
var event:WhiteboardDrawEvent = new WhiteboardDrawEvent(WhiteboardDrawEvent.UNDO);
|
||||
event.wbId = currentWhiteboardId;
|
||||
var dispatcher:Dispatcher = new Dispatcher();
|
||||
dispatcher.dispatchEvent(event);
|
||||
}
|
||||
|
||||
public function sendClearToServer():void {
|
||||
var event:WhiteboardDrawEvent = new WhiteboardDrawEvent(WhiteboardDrawEvent.CLEAR);
|
||||
event.wbId = currentWhiteboardId;
|
||||
var dispatcher:Dispatcher = new Dispatcher();
|
||||
dispatcher.dispatchEvent(event);
|
||||
}
|
||||
|
||||
public function sendCursorPositionToServer(x:Number, y:Number):void {
|
||||
var event:WhiteboardCursorEvent = new WhiteboardCursorEvent(WhiteboardCursorEvent.SEND_CURSOR_POSITION);
|
||||
event.xPercent = x;
|
||||
event.yPercent = y;
|
||||
dispatcher.dispatchEvent(event);
|
||||
}
|
||||
|
||||
@ -214,16 +250,21 @@ package org.bigbluebutton.modules.whiteboard.views {
|
||||
CursorManager.removeCursor(CursorManager.currentCursorID);
|
||||
}
|
||||
|
||||
public function doesContain(child:DisplayObject):Boolean {
|
||||
private function getMouseXY():Point {
|
||||
return new Point(Math.min(Math.max(parent.mouseX, 0), parent.width-1) - this.x, Math.min(Math.max(parent.mouseY, 0), parent.height-1) - this.y);
|
||||
}
|
||||
|
||||
private function presenterChange(amIPresenter:Boolean, presenterId:String):void {
|
||||
canvasModel.presenterChange(amIPresenter, presenterId);
|
||||
canvasDisplayModel.presenterChange(amIPresenter, presenterId);
|
||||
}
|
||||
|
||||
public function doesContainGraphic(child:DisplayObject):Boolean {
|
||||
return this.graphicObjectHolder.rawChildren.contains(child);
|
||||
}
|
||||
|
||||
public function getMouseXY():Array {
|
||||
return [Math.min(Math.max(parent.mouseX, 0), parent.width-2) - this.x, Math.min(Math.max(parent.mouseY, 0), parent.height-2) - this.y];
|
||||
}
|
||||
|
||||
public function removeGraphic(child:DisplayObject):void {
|
||||
if (doesContain(child)) this.graphicObjectHolder.rawChildren.removeChild(child);
|
||||
if (doesContainGraphic(child)) this.graphicObjectHolder.rawChildren.removeChild(child);
|
||||
else trace("Does not contain");
|
||||
}
|
||||
|
||||
@ -231,6 +272,18 @@ package org.bigbluebutton.modules.whiteboard.views {
|
||||
this.graphicObjectHolder.rawChildren.addChild(child);
|
||||
}
|
||||
|
||||
private function doesContainCursor(cursor:DisplayObject):Boolean {
|
||||
return this.cursorObjectHolder.rawChildren.contains(cursor);
|
||||
}
|
||||
|
||||
public function addCursor(cursor:DisplayObject):void {
|
||||
this.cursorObjectHolder.rawChildren.addChild(cursor);
|
||||
}
|
||||
|
||||
public function removeCursorChild(cursor:DisplayObject):void {
|
||||
if (doesContainCursor(cursor)) this.cursorObjectHolder.rawChildren.removeChild(cursor);
|
||||
}
|
||||
|
||||
public function textToolbarSyncProxy(tobj:TextObject):void {
|
||||
textToolbar.syncPropsWith(tobj);
|
||||
}
|
||||
@ -243,6 +296,8 @@ package org.bigbluebutton.modules.whiteboard.views {
|
||||
public function zoomCanvas(width:Number, height:Number):void {
|
||||
graphicObjectHolder.width = width;
|
||||
graphicObjectHolder.height = height;
|
||||
cursorObjectHolder.width = width;
|
||||
cursorObjectHolder.height = height;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
canvasDisplayModel.zoomCanvas(width, height);
|
||||
@ -282,9 +337,14 @@ package org.bigbluebutton.modules.whiteboard.views {
|
||||
private function onModifiedAccess(e:WhiteboardAccessEvent):void {
|
||||
//if (e.whiteboardId == currentWhiteboardId) {
|
||||
whiteboardToolbar.whiteboardAccessModified(e.multiUser);
|
||||
canvasModel.multiUserChange(e.multiUser);
|
||||
//}
|
||||
}
|
||||
|
||||
private function onReceivedCursorPosition(e:WhiteboardCursorEvent):void {
|
||||
canvasDisplayModel.drawCursor(e.userId, e.xPercent, e.yPercent);
|
||||
}
|
||||
|
||||
private function onEnableWhiteboardEvent(e:WhiteboardButtonEvent):void {
|
||||
e.stopPropagation();
|
||||
|
||||
@ -298,5 +358,17 @@ package org.bigbluebutton.modules.whiteboard.views {
|
||||
this.whiteboardEnabled = false;
|
||||
setWhiteboardInteractable();
|
||||
}
|
||||
|
||||
private function onSwitchToPresenterEvent(e:MadePresenterEvent):void {
|
||||
presenterChange(true, e.userID);
|
||||
}
|
||||
|
||||
private function onSwitchToViewerEvent(e:MadePresenterEvent):void {
|
||||
presenterChange(false, e.userID);
|
||||
}
|
||||
|
||||
private function onUserLeftEvent(e:UserLeftEvent):void {
|
||||
canvasDisplayModel.userLeft(e.userID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,102 @@
|
||||
/**
|
||||
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
|
||||
*
|
||||
* Copyright (c) 2017 BigBlueButton Inc. and by respective authors (see below).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the
|
||||
* terms of the GNU Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 3.0 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along
|
||||
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.bigbluebutton.modules.whiteboard.views {
|
||||
import flash.display.Shape;
|
||||
|
||||
public class WhiteboardCursor extends Shape {
|
||||
private static const PRESENTER_COLOR:uint = 0xFF0000;
|
||||
private static const OTHER_COLOR:uint = 0x00FF00;
|
||||
|
||||
private var _userId:String;
|
||||
private var _origX:Number;
|
||||
private var _origY:Number;
|
||||
private var _parentWidth:Number;
|
||||
private var _parentHeight:Number;
|
||||
private var _isPresenter:Boolean;
|
||||
|
||||
public function WhiteboardCursor(userId:String, x:Number, y:Number, parentWidth:Number, parentHeight:Number, isPresenter:Boolean) {
|
||||
_userId = userId;
|
||||
_origX = x;
|
||||
_origY = y;
|
||||
_parentWidth = parentWidth;
|
||||
_parentHeight = parentHeight;
|
||||
_isPresenter = isPresenter;
|
||||
|
||||
drawCursor();
|
||||
setPosition();
|
||||
}
|
||||
|
||||
public function updatePosition(x:Number, y:Number):void {
|
||||
_origX = x;
|
||||
_origY = y;
|
||||
|
||||
setPosition();
|
||||
}
|
||||
|
||||
public function updateParentSize(parentWidth:Number, parentHeight:Number):void {
|
||||
_parentWidth = parentWidth;
|
||||
_parentHeight = parentHeight;
|
||||
|
||||
setPosition();
|
||||
}
|
||||
|
||||
public function updatePresenter(isPresenter:Boolean):void {
|
||||
_isPresenter = isPresenter;
|
||||
|
||||
drawCursor();
|
||||
}
|
||||
|
||||
private function setPosition():void {
|
||||
x = denormalize(_origX, _parentWidth);
|
||||
y = denormalize(_origY, _parentHeight);
|
||||
|
||||
if (isCursorOutsideWindow()) {
|
||||
hideCursor()
|
||||
} else {
|
||||
showCursor();
|
||||
}
|
||||
}
|
||||
|
||||
private function showCursor():void {
|
||||
visible = true;
|
||||
}
|
||||
|
||||
private function hideCursor():void{
|
||||
visible = false;
|
||||
}
|
||||
|
||||
private function isCursorOutsideWindow():Boolean {
|
||||
return (_origX > 100 || _origX < 0 ||
|
||||
_origY > 100 || _origY < 0);
|
||||
}
|
||||
|
||||
private function drawCursor():void {
|
||||
var cursorColor:uint = (_isPresenter ? PRESENTER_COLOR : OTHER_COLOR);
|
||||
|
||||
graphics.clear();
|
||||
graphics.lineStyle(6, cursorColor, 0.6);
|
||||
graphics.drawCircle(0,0,2.5);
|
||||
}
|
||||
|
||||
private function denormalize(val:Number, side:Number):Number {
|
||||
return (val*side)/100.0;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user