diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/RecorderActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/RecorderActor.scala index 17223539fc3458e164b966ec54562130441f510c..f4b45140767f0b20f8ddbb890f42ac170fcf8a6b 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/RecorderActor.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/RecorderActor.scala @@ -411,7 +411,7 @@ class RecorderActor(val recorder: RecorderApplication) private def handleSendWhiteboardAnnotationEvent(msg: SendWhiteboardAnnotationEvent) { if (msg.recorded) { - if ((msg.shape.shapeType == WhiteboardKeyUtil.TEXT_TYPE) && (msg.shape.status != WhiteboardKeyUtil.TEXT_CREATED_STATUS)) { + if ((msg.shape.shapeType == WhiteboardKeyUtil.TEXT_TYPE) && (msg.shape.status != WhiteboardKeyUtil.DRAW_START_STATUS)) { val event = new ModifyTextWhiteboardRecordEvent() event.setMeetingId(msg.meetingID) diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/WhiteboardApp.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/WhiteboardApp.scala index 5f578069490a239a163bc0a7c50db2c0bc460384..507299a5130a809fa893f16fbea0337001563c20 100755 --- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/WhiteboardApp.scala +++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/WhiteboardApp.scala @@ -23,16 +23,15 @@ trait WhiteboardApp { // println("Received whiteboard shape. status=[" + status + "], shapeType=[" + shapeType + "]") - if (WhiteboardKeyUtil.TEXT_CREATED_STATUS == status || WhiteboardKeyUtil.DRAW_START_STATUS == status) { - // println("Received textcreated status") + if (WhiteboardKeyUtil.DRAW_START_STATUS == status) { liveMeeting.wbModel.addAnnotation(wbId, userId, shape) - } else if (WhiteboardKeyUtil.TEXT_EDITED_STATUS == status || WhiteboardKeyUtil.DRAW_UPDATE_STATUS == status) { + } else if (WhiteboardKeyUtil.DRAW_UPDATE_STATUS == status) { if (WhiteboardKeyUtil.PENCIL_TYPE == shapeType) { liveMeeting.wbModel.updateAnnotationPencil(wbId, userId, shape) } else { liveMeeting.wbModel.updateAnnotation(wbId, userId, shape) } - } else if (WhiteboardKeyUtil.TEXT_PUBLISHED_STATUS == status || WhiteboardKeyUtil.DRAW_END_STATUS == status) { + } else if (WhiteboardKeyUtil.DRAW_END_STATUS == status) { if (WhiteboardKeyUtil.PENCIL_TYPE == shapeType) { shape = liveMeeting.wbModel.endAnnotationPencil(wbId, userId, shape) } else { diff --git a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/WhiteboardKeyUtil.java b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/WhiteboardKeyUtil.java index 2e6b1a123556b98dff7850e157cd223799cf69d0..36e2a14d0c885384024c9acca65694de751f80ff 100755 --- a/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/WhiteboardKeyUtil.java +++ b/bbb-common-message/src/main/java/org/bigbluebutton/common/messages/WhiteboardKeyUtil.java @@ -7,11 +7,8 @@ public class WhiteboardKeyUtil { public static final String ELLIPSE_TYPE = "ellipse"; public static final String TRIANGLE_TYPE = "triangle"; public static final String LINE_TYPE = "line"; - public static final String TEXT_CREATED_STATUS = "textCreated"; - public static final String TEXT_EDITED_STATUS = "textEdited"; - public static final String TEXT_PUBLISHED_STATUS = "textPublished"; public static final String DRAW_START_STATUS = "DRAW_START"; - public static final String DRAW_UPDATE_STATUS = "DRAW_UPDATE"; + public static final String DRAW_UPDATE_STATUS = "DRAW_UPDATE"; public static final String DRAW_END_STATUS = "DRAW_END"; public static final String POLL_RESULT_TYPE = "poll_result"; } diff --git a/bigbluebutton-client/src/org/bigbluebutton/common/Images.as b/bigbluebutton-client/src/org/bigbluebutton/common/Images.as index efc1249a6808f01e224a4489debe498c6acce16f..9dab0aa6e953ded01fcf3fea5f07d3a149e790dc 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/common/Images.as +++ b/bigbluebutton-client/src/org/bigbluebutton/common/Images.as @@ -73,9 +73,6 @@ package org.bigbluebutton.common [Embed(source="assets/images/hand.png")] public var hand_icon:Class; - [Embed(source="assets/images/marker.png")] - public var scribble_icon:Class; - [Embed(source="assets/images/text.png")] public var text_icon:Class; @@ -137,33 +134,9 @@ package org.bigbluebutton.common [Embed(source="assets/images/line.png")] public var line_icon:Class; -// [Embed(source="assets/images/text_icon.png")] -// public var text_icon:Class; - - [Embed(source="assets/images/fill_icon.png")] - public var fill_icon:Class; - - [Embed(source="assets/images/transparency_icon.png")] - public var transparency_icon:Class; - - [Embed(source="assets/images/eraser.png")] - public var eraser_icon:Class; - - [Embed(source="assets/images/highlighter_icon.png")] - public var highlighter_icon:Class; - - [Embed(source="assets/images/pointer_icon_small.png")] - public var select_icon:Class; - [Embed(source="assets/images/triangle.png")] public var triangle_icon:Class; - [Embed(source="assets/images/text_background_icon.png")] - public var toggle_text_background_icon:Class; - - [Embed(source="assets/images/grid_icon.png")] - public var grid_icon:Class; - [Embed(source="assets/images/ic_refresh_16px.png")] public var refreshSmall:Class; diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/present/events/NavigationEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/present/events/NavigationEvent.as deleted file mode 100755 index 2797917079eb65d220454f940f5282867ad7ce4d..0000000000000000000000000000000000000000 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/present/events/NavigationEvent.as +++ /dev/null @@ -1,37 +0,0 @@ -/** -* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ -* -* Copyright (c) 2012 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.present.events -{ - import flash.events.Event; - - public class NavigationEvent extends Event - { - public static const GOTO_PAGE:String = "GOTO_PAGE"; - public static const BIND_KEYBOARD_EVENT:String = "Bind to keyboard events"; - - public var pageNumber:Number; - public var bindToKeyboard:Boolean = false; - - public function NavigationEvent(type:String) - { - super(type, true, false); - } - - } -} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/PresentationWindow.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/PresentationWindow.mxml index ae84848d96f02db22e68f480eac0b200301fd2a3..4af2f02731c8a88e1a39a65887d73e08d0615e75 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/PresentationWindow.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/present/ui/views/PresentationWindow.mxml @@ -48,7 +48,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. <mate:Listener type="{MadePresenterEvent.SWITCH_TO_PRESENTER_MODE}" method="handleBecomePresenter" /> <mate:Listener type="{MadePresenterEvent.SWITCH_TO_VIEWER_MODE}" method="handleBecomeViewer" /> <mate:Listener type="{PresentationChangedEvent.PRESENTATION_CHANGED_EVENT}" method="handlePresentationChangedEvent" /> - <mate:Listener type="{NavigationEvent.BIND_KEYBOARD_EVENT}" method="bindToKeyboardEvents" /> <mate:Listener type="{UploadEvent.CLEAR_PRESENTATION}" method="clearPresentation" /> <mate:Listener type="{DisplaySlideEvent.DISPLAY_SLIDE_EVENT}" method="handleDisplaySlideEvent" /> <mate:Listener type="{AddOverlayCanvasEvent.ADD_OVERLAY_CANVAS}" method="addOverlayCanvas" /> @@ -113,7 +112,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. import org.bigbluebutton.modules.present.events.AddOverlayCanvasEvent; import org.bigbluebutton.modules.present.events.DisplaySlideEvent; import org.bigbluebutton.modules.present.events.DownloadEvent; - import org.bigbluebutton.modules.present.events.NavigationEvent; import org.bigbluebutton.modules.present.events.PresentationChangedEvent; import org.bigbluebutton.modules.present.events.PresenterCommands; import org.bigbluebutton.modules.present.events.RemovePresentationEvent; @@ -193,7 +191,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. thumbY = this.height - 160; - bindKeyboardEvents(); this.addEventListener(MDIWindowEvent.RESIZE_END, onResizeEndEvent); resourcesChanged(); @@ -206,7 +203,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. t.addEventListener(TimerEvent.TIMER, addWhiteboardToolbar); t.start(); - presenterTabs.addEventListener(MouseEvent.CLICK, onSelectTabEvent, true); + presenterTabs.addEventListener(Event.CHANGE, onSelectTabEvent, true); if (UsersUtil.amIPresenter()) { becomePresenter(); @@ -329,44 +326,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. } } - private function bindToKeyboardEvents(event:NavigationEvent):void { - if (event.bindToKeyboard) { - LOGGER.debug("******************************************** Binding to keyboard events ********************"); - bindKeyboardEvents(); - } else { - LOGGER.debug("********************************************* Unbinding to keyboard events *****************"); - unbindKeyboardEvents(); - } - } - - private function unbindKeyboardEvents():void { - stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp); - } - - private function bindKeyboardEvents():void { - stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); - } - - // Maybe there's a problem in here too? - private function onKeyUp(event:KeyboardEvent):void { - /*if (event.shiftKey && event.ctrlKey) { - switch (event.keyCode) { - case Keyboard.LEFT: - case Keyboard.UP: - case Keyboard.PAGE_UP: - gotoPreviousSlide(); - break; - case Keyboard.DOWN: - case Keyboard.RIGHT: - case Keyboard.SPACE: - case Keyboard.PAGE_DOWN: - case Keyboard.ENTER: - gotoNextSlide(); - break; - } - }*/ - } - public function getPrefferedPosition():String{ return MainCanvas.MIDDLE; } @@ -936,7 +895,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. onSelectTab(); } - private function onSelectTabEvent(event:MouseEvent):void { + private function onSelectTabEvent(event:Event):void { onSelectTab(); } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/WhiteboardCanvasDisplayModel.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/WhiteboardCanvasDisplayModel.as index e3805dddca14ba81159728a852406b998e59307a..774f42e079893e9349f1fa3ec18ca5262a45d090 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/WhiteboardCanvasDisplayModel.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/WhiteboardCanvasDisplayModel.as @@ -29,18 +29,17 @@ package org.bigbluebutton.modules.whiteboard import org.bigbluebutton.common.IBbbCanvas; import org.bigbluebutton.core.managers.UserManager; import org.bigbluebutton.main.events.MadePresenterEvent; - import org.bigbluebutton.modules.present.events.NavigationEvent; import org.bigbluebutton.modules.whiteboard.business.shapes.DrawObject; import org.bigbluebutton.modules.whiteboard.business.shapes.GraphicFactory; import org.bigbluebutton.modules.whiteboard.business.shapes.GraphicObject; import org.bigbluebutton.modules.whiteboard.business.shapes.ShapeFactory; import org.bigbluebutton.modules.whiteboard.business.shapes.TextObject; import org.bigbluebutton.modules.whiteboard.business.shapes.WhiteboardConstants; - import org.bigbluebutton.modules.whiteboard.events.GraphicObjectFocusEvent; import org.bigbluebutton.modules.whiteboard.events.WhiteboardDrawEvent; import org.bigbluebutton.modules.whiteboard.events.WhiteboardUpdate; import org.bigbluebutton.modules.whiteboard.models.Annotation; import org.bigbluebutton.modules.whiteboard.models.WhiteboardModel; + import org.bigbluebutton.modules.whiteboard.views.TextUpdateListener; import org.bigbluebutton.modules.whiteboard.views.WhiteboardCanvas; /** @@ -49,168 +48,71 @@ package org.bigbluebutton.modules.whiteboard public class WhiteboardCanvasDisplayModel { private static const LOGGER:ILogger = getClassLogger(WhiteboardCanvasDisplayModel); - public var whiteboardModel:WhiteboardModel; - public var wbCanvas:WhiteboardCanvas; + private var whiteboardModel:WhiteboardModel; + private var wbCanvas:WhiteboardCanvas; private var _annotationsList:Array = new Array(); private var shapeFactory:ShapeFactory = new ShapeFactory(); - private var currentlySelectedTextObject:TextObject = null; - + private var textUpdateListener:TextUpdateListener = new TextUpdateListener(); + private var bbbCanvas:IBbbCanvas; private var width:Number; private var height:Number; private var zoomPercentage:Number = 1; - public function doMouseDown(mouseX:Number, mouseY:Number):void { - publishText(); - } - - private function publishText():void { - /** - * Check if the presenter is starting a new text annotation without committing the last one. - * If so, publish the last text annotation. - */ - if (needToPublish()) { - sendTextToServer(TextObject.TEXT_PUBLISHED, currentlySelectedTextObject); - } - } + public function setDependencies(whiteboardCanvas:WhiteboardCanvas, whiteboardModel:WhiteboardModel):void { + wbCanvas = whiteboardCanvas; + this.whiteboardModel = whiteboardModel; + + textUpdateListener.setDependencies(wbCanvas, whiteboardModel, shapeFactory); + } - public function needToPublish() : Boolean { - return currentlySelectedTextObject != null && currentlySelectedTextObject.status != TextObject.TEXT_PUBLISHED; + public function isEditingText():Boolean { + return textUpdateListener.isEditingText(); } + + public function doMouseDown(mouseX:Number, mouseY:Number):void { + if (textUpdateListener) textUpdateListener.canvasMouseDown(); + } - public function drawGraphic(event:WhiteboardUpdate):void{ + public function drawGraphic(event:WhiteboardUpdate):void { var o:Annotation = event.annotation; // LogUtil.debug("**** Drawing graphic [" + o.type + "] *****"); - if (o.type != DrawObject.TEXT) { - var dobj:DrawObject; - switch (o.status) { - case DrawObject.DRAW_START: - dobj = shapeFactory.makeDrawObject(o, whiteboardModel); - if (dobj != null) { - dobj.draw(o, shapeFactory.parentWidth, shapeFactory.parentHeight, zoomPercentage); - wbCanvas.addGraphic(dobj); - _annotationsList.push(dobj); - } - break; - case DrawObject.DRAW_UPDATE: - case DrawObject.DRAW_END: - var gobj:GraphicObject; - for (var i:int = _annotationsList.length -1; i >= 0; i--) { - gobj = _annotationsList[i] as GraphicObject; - if (gobj != null && gobj.id == o.id) { - gobj.updateAnnotation(o); - return; - } - } - - dobj = shapeFactory.makeDrawObject(o, whiteboardModel); - if (dobj != null) { - dobj.draw(o, shapeFactory.parentWidth, shapeFactory.parentHeight, zoomPercentage); - wbCanvas.addGraphic(dobj); - _annotationsList.push(dobj); - } - break; - } - } else { - drawText(o); - } - } - - // Draws a TextObject when/if it is received from the server - private function drawText(o:Annotation):void { - trace("Text status="+o.status); + var gobj:GraphicObject; switch (o.status) { - case TextObject.TEXT_CREATED: - trace("new text, userid="+o.userId+" my id="+UserManager.getInstance().getConference().getMyUserId()); - if (o.userId == UserManager.getInstance().getConference().getMyUserId()) - addPresenterText(o, true); - else - addNormalText(o); - break; - case TextObject.TEXT_UPDATED: - if (o.userId != UserManager.getInstance().getConference().getMyUserId()) { - modifyText(o); - } + case DrawObject.DRAW_START: + createGraphic(o); break; - case TextObject.TEXT_PUBLISHED: - modifyText(o); - // Inform others that we are done with listening for events and that they should re-listen for keyboard events. - if (o.userId == UserManager.getInstance().getConference().getMyUserId()) { - bindToKeyboardEvents(true); - wbCanvas.stage.focus = null; - currentlySelectedTextObject = null; + case DrawObject.DRAW_UPDATE: + case DrawObject.DRAW_END: + for (var i:int = _annotationsList.length -1; i >= 0; i--) { + gobj = _annotationsList[i] as GraphicObject; + if (gobj != null && gobj.id == o.id) { + gobj.updateAnnotation(o); + return; + } } + + createGraphic(o); break; - } - } - - /* adds a new TextObject that is suited for a presenter. For example, it will be made editable and the appropriate listeners will be registered so that - the required events will be dispatched */ - private function addPresenterText(o:Annotation, background:Boolean=false):void { - /** - * We will not be listening for keyboard events to input texts. Tell others to not listen for these events. For example, the presentation module - * listens for Keyboard.ENTER, Keyboard.SPACE to advance the slides. We don't want that while the presenter is typing texts. - */ - bindToKeyboardEvents(false); - - var tobj:TextObject = shapeFactory.makeTextObject(o); - tobj.setGraphicID(o.id); - tobj.status = o.status; - tobj.userId = o.userId; - tobj.multiline = true; - tobj.wordWrap = true; - - if (background) { - tobj.makeEditable(true); - tobj.border = true; - tobj.background = true; - tobj.backgroundColor = 0xFFFFFF; - } - - tobj.registerListeners(textObjGainedFocusListener, textObjLostFocusListener, textObjTextChangeListener, textObjSpecialListener); - - tobj._whiteboardID = whiteboardModel.getCurrentWhiteboardId(); - - wbCanvas.addGraphic(tobj); - wbCanvas.stage.focus = tobj; - _annotationsList.push(tobj); - - } - - /* adds a new TextObject that is suited for a viewer. For example, it will not - be made editable and no listeners need to be attached because the viewers - should not be able to edit/modify the TextObject - */ - private function addNormalText(o:Annotation):void { - var tobj:TextObject = shapeFactory.makeTextObject(o); - tobj.setGraphicID(o.id); - tobj.status = o.status; - tobj.userId = o.userId; - tobj.multiline = true; - tobj.wordWrap = true; - tobj.background = false; - tobj.makeEditable(false); - wbCanvas.addGraphic(tobj); - _annotationsList.push(tobj); - } - - private function removeText(id:String):void { - var tobjData:Array = getGobjInfoWithID(id); - if (tobjData != null) { - var removeIndex:int = tobjData[0]; - var tobjToRemove:TextObject = tobjData[1] as TextObject; - wbCanvas.removeGraphic(tobjToRemove); - _annotationsList.splice(removeIndex, 1); - } - } - - /* method to modify a TextObject that is already present on the whiteboard, as opposed to adding a new TextObject to the whiteboard */ - private function modifyText(o:Annotation):void { - removeText(o.id); - addNormalText(o); + } } + public function createGraphic(o:Annotation):void { + var gobj:GraphicObject = shapeFactory.makeGraphicObject(o, whiteboardModel); + if (gobj != null) { + gobj.draw(o, shapeFactory.parentWidth, shapeFactory.parentHeight, zoomPercentage); + wbCanvas.addGraphic(gobj as DisplayObject); + _annotationsList.push(gobj); + + if (o.type == DrawObject.TEXT && + o.status != DrawObject.DRAW_END && + o.userId == UserManager.getInstance().getConference().getMyUserId()) { + textUpdateListener.newTextObject(gobj as TextObject); + } + } + } + /* the following three methods are used to remove any GraphicObjects (and its subclasses) if the id of the object to remove is specified. The latter two are convenience methods, the main one is the first of the three. */ @@ -219,15 +121,11 @@ package org.bigbluebutton.modules.whiteboard var removeIndex:int = gobjData[0]; var gobjToRemove:GraphicObject = gobjData[1] as GraphicObject; wbCanvas.removeGraphic(gobjToRemove as DisplayObject); - _annotationsList.splice(removeIndex, 1); - } - - private function removeShape(id:String):void { - var dobjData:Array = getGobjInfoWithID(id); - var removeIndex:int = dobjData[0]; - var dobjToRemove:DrawObject = dobjData[1] as DrawObject; - wbCanvas.removeGraphic(dobjToRemove); - _annotationsList.splice(removeIndex, 1); + _annotationsList.splice(removeIndex, 1); + + if (gobjToRemove.toolType == WhiteboardConstants.TYPE_TEXT) { + textUpdateListener.removedTextObject(gobjToRemove as TextObject); + } } /* returns an array of the GraphicObject that has the specified id, @@ -248,35 +146,10 @@ package org.bigbluebutton.modules.whiteboard private function removeLastGraphic():void { var gobj:GraphicObject = _annotationsList.pop(); - if (gobj.type == WhiteboardConstants.TYPE_TEXT) { - (gobj as TextObject).makeEditable(false); - (gobj as TextObject).deregisterListeners(textObjGainedFocusListener, textObjLostFocusListener, textObjTextChangeListener, textObjSpecialListener); - } - wbCanvas.removeGraphic(gobj as DisplayObject); - } - - // returns all DrawObjects in graphicList - private function getAllShapes():Array { - var shapes:Array = new Array(); - for(var i:int = 0; i < _annotationsList.length; i++) { - var currGobj:GraphicObject = _annotationsList[i]; - if(currGobj.type == WhiteboardConstants.TYPE_SHAPE) { - shapes.push(currGobj as DrawObject); - } + if (gobj.toolType == WhiteboardConstants.TYPE_TEXT) { + textUpdateListener.removedTextObject(gobj as TextObject); } - return shapes; - } - - // returns all TextObjects in graphicList - private function getAllTexts():Array { - var texts:Array = new Array(); - for(var i:int = 0; i < _annotationsList.length; i++) { - var currGobj:GraphicObject = _annotationsList[i]; - if(currGobj.type == WhiteboardConstants.TYPE_TEXT) { - texts.push(currGobj as TextObject) - } - } - return texts; + wbCanvas.removeGraphic(gobj as DisplayObject); } public function clearBoard(event:WhiteboardUpdate = null):void { @@ -293,19 +166,11 @@ package org.bigbluebutton.modules.whiteboard removeLastGraphic(); } } - wbCanvas.textToolbar.visible = false; } public function undoAnnotation(annotation:Annotation):void { if (this._annotationsList.length > 0) { - if (annotation.type == DrawObject.TEXT) { - if (currentlySelectedTextObject && currentlySelectedTextObject.id == annotation.id) { - wbCanvas.textToolbar.visible = false; - } - removeText(annotation.id); - } else { - removeGraphic(annotation.id); - } + removeGraphic(annotation.id); } } @@ -313,27 +178,20 @@ package org.bigbluebutton.modules.whiteboard var annotations:Array = whiteboardModel.getAnnotations(wbId); for (var i:int = 0; i < annotations.length; i++) { var an:Annotation = annotations[i] as Annotation; - if ( an.type != DrawObject.TEXT) { - var dobj:DrawObject = shapeFactory.makeDrawObject(an, whiteboardModel); - if (dobj != null) { - dobj.draw(an, shapeFactory.parentWidth, shapeFactory.parentHeight, zoomPercentage); - wbCanvas.addGraphic(dobj); - _annotationsList.push(dobj); - } - } else { - if (an.annotation.text != "") { - addNormalText(an); - } - } + var gobj:GraphicObject = shapeFactory.makeGraphicObject(an, whiteboardModel); + if (gobj != null) { + gobj.draw(an, shapeFactory.parentWidth, shapeFactory.parentHeight, zoomPercentage); + wbCanvas.addGraphic(gobj as DisplayObject); + _annotationsList.push(gobj); + } } if (_annotationsList.length > 0) { for (var ij:int = 0; ij < this._annotationsList.length; ij++){ redrawGraphic(this._annotationsList[ij] as GraphicObject, ij); - } } } - + } /********************************************************* * HACK! HACK! HACK! HACK! HACK! HACK! HACK! HACK! HACK! * To tell us that the Whiteboard Canvas has been overlayed into the Presentation Canvas. @@ -357,7 +215,7 @@ package org.bigbluebutton.modules.whiteboard /**********************************************************/ public function changePage(wbId:String):void{ - publishText(); + textUpdateListener.canvasMouseDown(); // LogUtil.debug("**** CanvasDisplay changePage. Clearing page *****"); clearBoard(); @@ -375,16 +233,12 @@ package org.bigbluebutton.modules.whiteboard for (var i:int = 0; i < annotations.length; i++) { var an:Annotation = annotations[i] as Annotation; // LogUtil.debug("**** Drawing graphic from changePage [" + an.type + "] *****"); - if(an.type != DrawObject.TEXT) { - var dobj:DrawObject = shapeFactory.makeDrawObject(an, whiteboardModel); - if (dobj != null) { - dobj.draw(an, shapeFactory.parentWidth, shapeFactory.parentHeight, zoomPercentage); - wbCanvas.addGraphic(dobj); - _annotationsList.push(dobj); - } - } else { - addNormalText(an); - } + var gobj:GraphicObject = shapeFactory.makeGraphicObject(an, whiteboardModel); + if (gobj != null) { + gobj.draw(an, shapeFactory.parentWidth, shapeFactory.parentHeight, zoomPercentage); + wbCanvas.addGraphic(gobj as DisplayObject); + _annotationsList.push(gobj); + } } for (var ij:int = 0; ij < this._annotationsList.length; ij++){ @@ -402,171 +256,14 @@ package org.bigbluebutton.modules.whiteboard for (var i:int = 0; i < this._annotationsList.length; i++){ redrawGraphic(this._annotationsList[i] as GraphicObject, i); } - wbCanvas.textToolbar.visible = false; } private function redrawGraphic(gobj:GraphicObject, objIndex:int):void { - var o:Annotation; - if (gobj.type != DrawObject.TEXT) { - - gobj.redraw(shapeFactory.parentWidth, shapeFactory.parentHeight, zoomPercentage); - - } else if(gobj.type == WhiteboardConstants.TYPE_TEXT) { - var origTobj:TextObject = gobj as TextObject; - var an:Annotation = whiteboardModel.getAnnotation(origTobj.id); - if (an != null) { - wbCanvas.removeGraphic(origTobj as DisplayObject); - // addNormalText(an); - var tobj:TextObject = shapeFactory.redrawTextObject(an, origTobj); - tobj.setGraphicID(origTobj.id); - tobj.status = origTobj.status; - tobj.multiline = true; - tobj.wordWrap = true; - tobj.background = false; - tobj.makeEditable(false); - tobj.background = false; - wbCanvas.addGraphic(tobj); - _annotationsList[objIndex] = tobj; - } - } - } - - /************************************************************************************************************************************** - * The following methods handles the presenter typing text into the textbox. The challenge here is how to maintain focus - * on the textbox while the presenter changes the size of the font and color. - * - * The text annotation will have 3 states (CREATED, EDITED, PUBLISHED). When the presenter creates a textbox, the other - * users are notified and the text annotation is in the CREATED state. The presenter can then type text, change size, font and - * the other users are updated. This is the EDITED state. When the presented hits the ENTER/RETURN key, the text is committed/published. - * - */ - public function textObjSpecialListener(event:KeyboardEvent):void { - // check for special conditions - if (event.keyCode == Keyboard.DELETE || event.keyCode == Keyboard.BACKSPACE || event.keyCode == Keyboard.ENTER) { - var sendStatus:String = TextObject.TEXT_UPDATED; - var tobj:TextObject = event.target as TextObject; - sendTextToServer(sendStatus, tobj); - } - // stops stops page changing when trying to navigate the text box - if (event.keyCode == Keyboard.LEFT || event.keyCode == Keyboard.RIGHT) { - event.stopPropagation(); - } - } - - public function textObjTextChangeListener(event:Event):void { - // The text is being edited. Notify others to update the text. - var sendStatus:String = TextObject.TEXT_UPDATED; - var tf:TextObject = event.target as TextObject; - sendTextToServer(sendStatus, tf); - } - - public function textObjGainedFocusListener(event:FocusEvent):void { -// LogUtil.debug("### GAINED FOCUS "); - // The presenter is ready to type in the text. Maintain focus to this textbox until the presenter hits the ENTER/RETURN key. - maintainFocusToTextBox(event); - } - - public function textObjLostFocusListener(event:FocusEvent):void { -// LogUtil.debug("### LOST FOCUS "); - // The presenter is moving the mouse away from the textbox. Perhaps to change the size and color of the text. - // Maintain focus to this textbox until the presenter hits the ENTER/RETURN key. - maintainFocusToTextBox(event); - } - - private function maintainFocusToTextBox(event:FocusEvent):void { - var tf:TextObject = event.currentTarget as TextObject; - if (wbCanvas.stage.focus != tf) wbCanvas.stage.focus = tf; - if (tf.stage.focus != tf) tf.stage.focus = tf; - currentlySelectedTextObject = tf; - var e:GraphicObjectFocusEvent = new GraphicObjectFocusEvent(GraphicObjectFocusEvent.OBJECT_SELECTED); - e.data = tf; - wbCanvas.dispatchEvent(e); - } - - public function modifySelectedTextObject(textColor:uint, bgColorVisible:Boolean, backgroundColor:uint, textSize:Number):void { - // The presenter has changed the color or size of the text. Notify others of these change. - currentlySelectedTextObject.textColor = textColor; - currentlySelectedTextObject.textSize = textSize; - currentlySelectedTextObject.applyFormatting(); - sendTextToServer(TextObject.TEXT_UPDATED, currentlySelectedTextObject); - } - - /***************************************************************************************************************************************/ - - /*** - * Tell others that it's ok for them to rebind to keyboard events as we are done with listening for keyboard events as - * input to the text annotation. - */ - private function bindToKeyboardEvents(bindToEvents:Boolean):void { - var navEvent:NavigationEvent = new NavigationEvent(NavigationEvent.BIND_KEYBOARD_EVENT); - navEvent.bindToKeyboard = bindToEvents; - wbCanvas.dispatchEvent(navEvent); - } - - private function sendTextToServer(status:String, tobj:TextObject):void { - switch (status) { - case TextObject.TEXT_CREATED: - tobj.status = TextObject.TEXT_CREATED; - break; - case TextObject.TEXT_UPDATED: - tobj.status = TextObject.TEXT_UPDATED; - break; - case TextObject.TEXT_PUBLISHED: - tobj.status = TextObject.TEXT_PUBLISHED; - break; - } - - if (status == TextObject.TEXT_PUBLISHED) { - tobj.deregisterListeners(textObjGainedFocusListener, textObjLostFocusListener, textObjTextChangeListener, textObjSpecialListener); - var e:GraphicObjectFocusEvent = new GraphicObjectFocusEvent(GraphicObjectFocusEvent.OBJECT_DESELECTED); - e.data = tobj; - wbCanvas.dispatchEvent(e); - - } - -// LogUtil.debug("SENDING TEXT: [" + tobj.textSize + "]"); - - var annotation:Object = new Object(); - annotation["type"] = "text"; - annotation["id"] = tobj.id; - annotation["status"] = tobj.status; - annotation["text"] = tobj.text; - annotation["fontColor"] = tobj.textColor; - annotation["backgroundColor"] = tobj.backgroundColor; - annotation["background"] = tobj.background; - annotation["x"] = tobj.getOrigX(); - annotation["y"] = tobj.getOrigY(); - annotation["dataPoints"] = tobj.getOrigX() + "," +tobj.getOrigY(); - annotation["fontSize"] = tobj.textSize; - annotation["calcedFontSize"] = GraphicFactory.normalize(tobj.textSize, shapeFactory.parentHeight); - annotation["textBoxWidth"] = tobj.textBoxWidth; - annotation["textBoxHeight"] = tobj.textBoxHeight; - - if (tobj._whiteboardID != null) { - annotation["whiteboardId"] = tobj._whiteboardID; - var msg:Annotation = new Annotation(tobj.id, "text", annotation); - wbCanvas.sendGraphicToServer(msg, WhiteboardDrawEvent.SEND_TEXT); - } - - - -/* - var tan:TextDrawAnnotation = shapeFactory.createTextObject(tobj.text, tobj.textColor, - tobj.getOrigX(), tobj.getOrigY(), tobj.textBoxWidth, tobj.textBoxHeight, tobj.textSize); - tan.id = tobj.id; - tan.status = tobj.status; - wbCanvas.sendGraphicToServer(tan.createAnnotation(whiteboardModel), WhiteboardDrawEvent.SEND_TEXT); -*/ - + gobj.redraw(shapeFactory.parentWidth, shapeFactory.parentHeight, zoomPercentage); } public function isPageEmpty():Boolean { return _annotationsList.length == 0; } - - /** Helper method to test whether this user is the presenter */ - private function get isPresenter():Boolean { - return UserManager.getInstance().getConference().amIPresenter; - } } } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/DrawObject.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/DrawObject.as index 88b8b170c5ec35a1c515fd58f0a531e2dfd048f9..6554618ba269fbdf3a006d5e56e9c23a456fca89 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/DrawObject.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/DrawObject.as @@ -62,12 +62,6 @@ package org.bigbluebutton.modules.whiteboard.business.shapes protected var _parentWidth:Number; protected var _parentHeight:Number; - /** - * ID we can use to match the shape in the client's view - * so we can use modify it; a unique identifier of each GraphicObject - */ - private var ID:String = WhiteboardConstants.ID_UNASSIGNED; - /** * The default constructor for the DrawObject * @@ -83,7 +77,7 @@ package org.bigbluebutton.modules.whiteboard.business.shapes return _id; } - public function get type():String { + public function get toolType():String { return _type; } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/GraphicObject.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/GraphicObject.as index f82f4ff557abb858482222e9405a2321a1f21c51..c8ae23d024df625a36791f82d021b083d20e7e76 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/GraphicObject.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/GraphicObject.as @@ -21,11 +21,13 @@ package org.bigbluebutton.modules.whiteboard.business.shapes import org.bigbluebutton.modules.whiteboard.models.Annotation; public interface GraphicObject { - function get type():String; + function get toolType():String; function get id():String; function get userId():String; + + function get status():String; function denormalize(val:Number, side:Number):Number; diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/ShapeFactory.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/ShapeFactory.as index c85d775c6aedd5b20ff2d4ebe8b47912d180e6d1..b4b635fc38d662e6a1276e1bb5f8536ea420b7b0 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/ShapeFactory.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/ShapeFactory.as @@ -53,7 +53,7 @@ package org.bigbluebutton.modules.whiteboard.business.shapes return _parentHeight; } - public function makeDrawObject(a:Annotation, whiteboardModel:WhiteboardModel):DrawObject{ + public function makeGraphicObject(a:Annotation, whiteboardModel:WhiteboardModel):GraphicObject{ if (a.type == DrawObject.PENCIL) { return new Pencil(a.id, a.type, a.status, a.userId); } else if (a.type == DrawObject.RECTANGLE) { @@ -66,8 +66,10 @@ package org.bigbluebutton.modules.whiteboard.business.shapes return new Triangle(a.id, a.type, a.status, a.userId); } else if (a.type == DrawObject.POLL) { return new PollResultObject(a.id, a.type, a.status, a.userId); + } else if (a.type == DrawObject.TEXT) { + return new TextObject(a.id, a.type, a.status, a.userId); } - + return null; } @@ -95,33 +97,11 @@ package org.bigbluebutton.modules.whiteboard.business.shapes return new Point(normalize(x, _parentWidth), normalize(y, _parentHeight)); } - public function createTextObject(txt:String, txtColor:uint, x:Number, y:Number, tbWidth:Number, tbHeight:Number, textSize:Number):TextDrawAnnotation { + public function createTextAnnotation(txt:String, txtColor:uint, x:Number, y:Number, tbWidth:Number, tbHeight:Number, textSize:Number):TextDrawAnnotation { var tobj:TextDrawAnnotation = new TextDrawAnnotation(txt, txtColor, normalize(x , _parentWidth), normalize(y, _parentHeight), normalize(tbWidth , _parentWidth), normalize(tbHeight , _parentHeight), textSize, normalize(textSize, _parentHeight)); return tobj; - } - - - /* convenience method for above method, takes a TextObject and returns one with "normalized" coordinates */ - public function makeTextObject(t:Annotation):TextObject { -// LogUtil.debug("***Making textObject [" + t.type + ", [" + t.annotation.x + "," + t.annotation.y + "]"); - var tobj:TextObject = new TextObject(t.annotation.text, t.annotation.fontColor, - t.annotation.x, t.annotation.y, t.annotation.textBoxWidth, - t.annotation.textBoxHeight, t.annotation.fontSize, t.annotation.calcedFontSize); - tobj.makeGraphic(_parentWidth,_parentHeight); -// LogUtil.debug("***Made textObject [" + tobj.text + ", [" + tobj.x + "," + tobj.y + "," + tobj.textSize + "]"); - return tobj; - } - - public function redrawTextObject(a:Annotation, t:TextObject):TextObject { -// LogUtil.debug("***Redraw textObject [" + a.type + ", [" + a.annotation.x + "," + a.annotation.y + "]"); - var tobj:TextObject = new TextObject(a.annotation.text, a.annotation.fontColor, - a.annotation.x, a.annotation.y, a.annotation.textBoxWidth, a.annotation.textBoxHeight, - a.annotation.fontSize, a.annotation.calcedFontSize); - tobj.redrawText(t.oldParentWidth, t.oldParentHeight, _parentWidth,_parentHeight); -// LogUtil.debug("***Redraw textObject [" + tobj.text + ", [" + tobj.x + "," + tobj.y + "," + tobj.textSize + "]"); - return tobj; - } + } } } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/TextObject.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/TextObject.as index c6ec2e374a01a785a3dba1f587b2756ba0963d77..4eb3e055bfe703eef2b861adda11205b54b4dc68 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/TextObject.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/business/shapes/TextObject.as @@ -16,215 +16,165 @@ * with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. * */ -package org.bigbluebutton.modules.whiteboard.business.shapes -{ - import flash.events.Event; - import flash.events.FocusEvent; - import flash.events.KeyboardEvent; - import flash.events.TextEvent; - import flash.text.AntiAliasType; - import flash.text.TextField; - import flash.text.TextFieldType; - import flash.text.TextFormat; - - import org.bigbluebutton.modules.whiteboard.models.Annotation; - - public class TextObject extends TextField implements GraphicObject { - public static const TYPE_NOT_EDITABLE:String = "dynamic"; - public static const TYPE_EDITABLE:String = "editable"; - - public static const TEXT_CREATED:String = "textCreated"; - public static const TEXT_UPDATED:String = "textEdited"; - public static const TEXT_PUBLISHED:String = "textPublished"; - - public static const TEXT_TOOL:String = "textTool"; - - /** - * Status = [CREATED, UPDATED, PUBLISHED] - */ - public var status:String = TEXT_CREATED; - - private var _userId:String = "undefined"; +package org.bigbluebutton.modules.whiteboard.business.shapes { + import flash.events.Event; + import flash.events.FocusEvent; + import flash.events.KeyboardEvent; + import flash.events.TextEvent; + import flash.text.AntiAliasType; + import flash.text.TextField; + import flash.text.TextFieldType; + import flash.text.TextFormat; - private var _editable:Boolean; - - /** - * ID we can use to match the shape in the client's view - * so we can use modify it; a unique identifier of each GraphicObject - */ - private var ID:String = WhiteboardConstants.ID_UNASSIGNED; - public var textSize:Number; - - private var _textBoxWidth:Number = 0; - private var _textBoxHeight:Number = 0; - private var origX:Number; - private var origY:Number; - private var _origParentWidth:Number = 0; - private var _origParentHeight:Number = 0; - public var fontStyle:String = "arial"; - private var _calcedFontSize:Number; + import org.bigbluebutton.core.managers.UserManager; + import org.bigbluebutton.modules.whiteboard.models.Annotation; - public var _whiteboardID:String; - - public function TextObject(text:String, textColor:uint, x:Number, y:Number, boxWidth:Number, - boxHeight:Number, textSize:Number, calcedFontSize:Number) { - this.text = text; - this.textColor = textColor; - origX = x; - origY = y; - this.x = x; - this.y = y; - _textBoxWidth = boxWidth; - _textBoxHeight = boxHeight; - this.textSize = textSize; - _calcedFontSize = calcedFontSize; - trace("width="+boxWidth+" height="+boxHeight+" x="+x+" y="+y); - this.mouseEnabled = false; - this.mouseWheelEnabled = false; - } - - public function get id():String { - return ID; - } - - override public function get type():String { - return WhiteboardConstants.TYPE_TEXT; - } - - public function get userId():String { - return _userId; - } + public class TextObject extends TextField implements GraphicObject { + private var _id:String; + private var _type:String; + private var _status:String; + private var _userId:String; + + protected var _ao:Object; + protected var _zoom:Number; + protected var _parentWidth:Number; + protected var _parentHeight:Number; + + private var _editable:Boolean; + private var _fontSize:Number; + + public function TextObject(id:String, type:String, status:String, userId:String) { + _id = id; + _type = type; + _status = status; + _userId = userId; + + mouseEnabled = false; + mouseWheelEnabled = false; + multiline = true; + wordWrap = true; + + //determine editability + makeEditable(userId == UserManager.getInstance().getConference().getMyUserId() && status != DrawObject.DRAW_END); + } + + public function get id():String { + return _id; + } + + public function get toolType():String { + return _type; + } + + public function get userId():String { + return _userId; + } + + public function get status():String { + return _status; + } + + public function get fontSize():Number { + return _fontSize; + } + + public function denormalize(val:Number, side:Number):Number { + return (val*side)/100.0; + } + + public function normalize(val:Number, side:Number):Number { + return (val*100.0)/side; + } + + public function draw(a:Annotation, parentWidth:Number, parentHeight:Number, zoom:Number):void { + _ao = a.annotation; + _parentWidth = parentWidth; + _parentHeight = parentHeight; + _zoom = zoom; + _fontSize = _ao.fontSize; + + makeGraphic(); + } - public function set userId(u:String):void { - _userId = u; - } - - public function getOrigX():Number { - return origX; - } - - public function getOrigY():Number { - return origY; - } - - public function setGraphicID(id:String):void { - this.ID = id; - } - - public function denormalize(val:Number, side:Number):Number { - return (val*side)/100.0; - } - - public function normalize(val:Number, side:Number):Number { - return (val*100.0)/side; - } - - public function draw(a:Annotation, parentWidth:Number, parentHeight:Number, zoom:Number):void {} - - public function updateAnnotation(a:Annotation):void {} - - public function redraw(parentWidth:Number, parentHeight:Number, zoom:Number):void {} - - private function applyTextFormat(size:Number):void { - var tf:TextFormat = new TextFormat(); - tf.size = size; - tf.font = "arial"; - this.defaultTextFormat = tf; - this.setTextFormat(tf); - } - - public function makeGraphic(parentWidth:Number, parentHeight:Number):void { - this.x = denormalize(origX, parentWidth); - this.y = denormalize(origY, parentHeight); - - var newFontSize:Number = textSize; - - if (_origParentHeight == 0 && _origParentWidth == 0) { - newFontSize = textSize; - _origParentHeight = parentHeight; - _origParentWidth = parentWidth; - } else { - newFontSize = (parentHeight/_origParentHeight) * textSize; - } - - newFontSize = denormalize(_calcedFontSize, parentHeight); - this.antiAliasType = AntiAliasType.ADVANCED; - applyTextFormat(newFontSize); + public function updateAnnotation(a:Annotation):void { + _ao = a.annotation; + _status = _ao.status; + + if (_status == DrawObject.DRAW_END) { + makeEditable(false); + } + + makeGraphic(); + } + + public function redraw(parentWidth:Number, parentHeight:Number, zoom:Number):void { + _parentWidth = parentWidth; + _parentHeight = parentHeight; + _zoom = zoom; + + makeGraphic(); + } + + private function makeGraphic():void { + x = denormalize(_ao.x, _parentWidth); + y = denormalize(_ao.y, _parentHeight); + + var fontSize:Number = denormalize(_ao.calcedFontSize * _zoom, _parentHeight); + applyTextFormat(fontSize); - this.width = denormalize(_textBoxWidth, parentWidth); - this.height = denormalize(_textBoxHeight, parentHeight); - } - - public function get textBoxWidth():Number { - return _textBoxWidth; - } - - public function get textBoxHeight():Number { - return _textBoxHeight; - } - - public function get oldParentWidth():Number { - return _origParentWidth; - } - - public function get oldParentHeight():Number { - return _origParentHeight; - } - - public function redrawText(origParentWidth:Number, origParentHeight:Number, parentWidth:Number, parentHeight:Number):void { - this.x = denormalize(origX, parentWidth); - this.y = denormalize(origY, parentHeight); - - var newFontSize:Number = textSize; - newFontSize = (parentHeight/origParentHeight) * textSize; - - /** Pass around the original parent width and height when this text was drawn. - * We need this to redraw the the text to the proper size properly. - * **/ - _origParentHeight = origParentHeight; - _origParentWidth = origParentWidth; - - newFontSize = denormalize(_calcedFontSize, parentHeight); - - this.antiAliasType = AntiAliasType.ADVANCED; - applyTextFormat(newFontSize); - - this.width = denormalize(_textBoxWidth, parentWidth); - this.height = denormalize(_textBoxHeight, parentHeight); - } - - public function makeEditable(editable:Boolean):void { - if(editable) { - this.type = TextFieldType.INPUT; - } else { - this.type = TextFieldType.DYNAMIC; - } - this._editable = editable; - } - - public function applyFormatting():void { - var tf:TextFormat = new TextFormat(); - tf.size = this.textSize; - tf.font = "arial"; - this.defaultTextFormat = tf; - this.setTextFormat(tf); - this.multiline = true; - this.wordWrap = true; - this.antiAliasType = AntiAliasType.ADVANCED; - } - - public function registerListeners(textObjGainedFocus:Function, textObjLostFocus:Function, textObjTextListener:Function, textObjDeleteListener:Function):void { - this.addEventListener(FocusEvent.FOCUS_IN, textObjGainedFocus); - this.addEventListener(FocusEvent.FOCUS_OUT, textObjLostFocus); - this.addEventListener(Event.CHANGE, textObjTextListener); - this.addEventListener(KeyboardEvent.KEY_DOWN, textObjDeleteListener); - } - - public function deregisterListeners(textObjGainedFocus:Function, textObjLostFocus:Function, textObjTextListener:Function, textObjDeleteListener:Function):void { - this.removeEventListener(FocusEvent.FOCUS_IN, textObjGainedFocus); - this.removeEventListener(FocusEvent.FOCUS_OUT, textObjLostFocus); - this.removeEventListener(TextEvent.TEXT_INPUT, textObjTextListener); - this.removeEventListener(KeyboardEvent.KEY_DOWN, textObjDeleteListener); - } - } + width = denormalize(_ao.textBoxWidth, _parentWidth); + height = denormalize(_ao.textBoxHeight, _parentHeight); + + if (!_editable) { + text = _ao.text; + textColor = _ao.textColor; + } + } + + private function applyTextFormat(size:Number):void { + var tf:TextFormat = new TextFormat(); + tf.size = size; + tf.font = "arial"; + defaultTextFormat = tf; + setTextFormat(tf); + + if (size < 48) { + antiAliasType = AntiAliasType.ADVANCED; + } else { + antiAliasType = AntiAliasType.NORMAL; + } + } + + private function makeEditable(editable:Boolean):void { + if(editable) { + type = TextFieldType.INPUT; + background = true; + border = true; + } else { + type = TextFieldType.DYNAMIC; + background = false; + border = false; + } + _editable = editable; + } + + public function applyNewFormat(fontColor:Number, fontSize:Number):void { + textColor = fontColor; + _fontSize = fontSize; + + applyTextFormat(fontSize); + } + + public function registerListeners(textObjLostFocus:Function, textObjTextListener:Function, textObjKeyDownListener:Function):void { + this.addEventListener(FocusEvent.FOCUS_OUT, textObjLostFocus); + this.addEventListener(Event.CHANGE, textObjTextListener); + this.addEventListener(KeyboardEvent.KEY_DOWN, textObjKeyDownListener); + } + + public function deregisterListeners(textObjLostFocus:Function, textObjTextListener:Function, textObjKeyDownListener:Function):void { + this.removeEventListener(FocusEvent.FOCUS_OUT, textObjLostFocus); + this.removeEventListener(Event.CHANGE, textObjTextListener); + this.removeEventListener(KeyboardEvent.KEY_DOWN, textObjKeyDownListener); + } + } } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/events/GraphicObjectFocusEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/events/GraphicObjectFocusEvent.as deleted file mode 100755 index cc584276013ed5c7e71ab5ad068605b099aa52c9..0000000000000000000000000000000000000000 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/events/GraphicObjectFocusEvent.as +++ /dev/null @@ -1,35 +0,0 @@ -/** -* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ -* -* Copyright (c) 2012 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.events -{ - import flash.events.Event; - import org.bigbluebutton.modules.whiteboard.business.shapes.TextObject; - - public class GraphicObjectFocusEvent extends Event - { - public static const OBJECT_SELECTED:String = "objSelect"; - public static const OBJECT_DESELECTED:String = "objDeselect"; - - public var data:TextObject; - - public function GraphicObjectFocusEvent(type:String) { - super(type, true, false); - } - } -} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/events/WhiteboardDrawEvent.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/events/WhiteboardDrawEvent.as index 0cd1af8068d1896343da6dfe31b86499e8df26df..5361200038abe373379ab1ee1d3db7e848ef2e71 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/events/WhiteboardDrawEvent.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/events/WhiteboardDrawEvent.as @@ -27,10 +27,8 @@ package org.bigbluebutton.modules.whiteboard.events public class WhiteboardDrawEvent extends Event { public static const SEND_SHAPE:String = "sendShape"; - public static const SEND_TEXT:String = "sendText"; public static const CLEAR:String = "WhiteboardClearCommand"; public static const UNDO:String = "WhiteboardUndoCommand"; - public static const NEW_SHAPE:String = "NewShapeEvent"; public static const GET_ANNOTATION_HISTORY:String = "WhiteboardGetAnnotationHistory"; diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/managers/WhiteboardManager.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/managers/WhiteboardManager.as index aae054b2eeb7130d61316d290ba8f76e84be120b..b7365daea25b84e3a04607f0459ee5cb1be2c8fc 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/managers/WhiteboardManager.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/managers/WhiteboardManager.as @@ -66,12 +66,11 @@ package org.bigbluebutton.modules.whiteboard.managers highlighterCanvas = new WhiteboardCanvas(); highlighterCanvas.model = model; highlighterCanvas.displayModel = displayModel; - displayModel.whiteboardModel = whiteboardModel; model.whiteboardModel = whiteboardModel model.wbCanvas = highlighterCanvas; - displayModel.wbCanvas = highlighterCanvas; - + displayModel.setDependencies(highlighterCanvas, whiteboardModel); + if (highlighterToolbar != null) return; highlighterToolbar = new WhiteboardToolbar(); diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/maps/WhiteboardEventMap.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/maps/WhiteboardEventMap.mxml index 57f39dccc972efd43f1f0c855fefa7a181f03c36..5a48ff385f2d2b736fc18c75279ad066b65da946 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/maps/WhiteboardEventMap.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/maps/WhiteboardEventMap.mxml @@ -26,7 +26,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. import org.bigbluebutton.main.events.BBBEvent; import org.bigbluebutton.main.events.ModuleStartedEvent; import org.bigbluebutton.modules.present.events.AddOverlayCanvasEvent; - import org.bigbluebutton.modules.present.events.NavigationEvent; import org.bigbluebutton.modules.present.events.PageLoadedEvent; import org.bigbluebutton.modules.present.events.PresentationEvent; import org.bigbluebutton.modules.present.events.UploadEvent; @@ -80,10 +79,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. <MethodInvoker generator="{WhiteboardService}" method="sendShape" arguments="{event}" /> </EventHandlers> - <EventHandlers type="{WhiteboardDrawEvent.SEND_TEXT}"> - <MethodInvoker generator="{WhiteboardService}" method="sendText" arguments="{event}" /> - </EventHandlers> - <EventHandlers type="{WhiteboardDrawEvent.UNDO}" > <MethodInvoker generator="{WhiteboardService}" method="undoGraphic" /> </EventHandlers> diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/models/WhiteboardModel.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/models/WhiteboardModel.as index c4b150f058210d4855cb17aff4430de2abe1f65d..28732b64617d4ff31bca7b278f87ed054d266685 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/models/WhiteboardModel.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/models/WhiteboardModel.as @@ -28,7 +28,6 @@ package org.bigbluebutton.modules.whiteboard.models import org.bigbluebutton.modules.present.model.Page; import org.bigbluebutton.modules.present.model.PresentationModel; import org.bigbluebutton.modules.whiteboard.business.shapes.DrawObject; - import org.bigbluebutton.modules.whiteboard.business.shapes.TextObject; import org.bigbluebutton.modules.whiteboard.events.WhiteboardPresenterEvent; import org.bigbluebutton.modules.whiteboard.events.WhiteboardShapesEvent; import org.bigbluebutton.modules.whiteboard.events.WhiteboardUpdate; @@ -59,8 +58,7 @@ package org.bigbluebutton.modules.whiteboard.models public function addAnnotation(annotation:Annotation):void { // LOGGER.debug("*** Adding annotation [{0},{1},{2}] ****", [annotation.id, annotation.type, annotation.status]); var wb:Whiteboard; - if (annotation.status == DrawObject.DRAW_START || annotation.type == DrawObject.POLL - || annotation.status == TextObject.TEXT_CREATED) { + if (annotation.status == DrawObject.DRAW_START || annotation.type == DrawObject.POLL) { wb = getWhiteboard(annotation.whiteboardId); if (wb != null) { wb.addAnnotation(annotation); diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/services/MessageSender.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/services/MessageSender.as index a3d741341c269340451c041ba3263f9d1138870f..e508fefef57a7e72b2e4971a8a8481c450d5d3a7 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/services/MessageSender.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/services/MessageSender.as @@ -124,24 +124,6 @@ package org.bigbluebutton.modules.whiteboard.services msg ); } - - /** - * Sends a TextObject to the Shared Object on the red5 server, and then triggers an update across all clients - * @param shape The shape sent to the SharedObject - * - */ - public function sendText(e:WhiteboardDrawEvent):void{ - var _nc:ConnectionManager = BBB.initConnectionManager(); - _nc.sendMessage("whiteboard.sendAnnotation", - function(result:String):void { // On successful result -// LogUtil.debug(result); - }, - function(status:String):void { // status - On error occurred - LOGGER.error(status); - }, - e.annotation.annotation - ); - } /** * Sends a shape to the Shared Object on the red5 server, and then triggers an update across all clients diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/services/WhiteboardService.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/services/WhiteboardService.as index c989a28b3e768aaf9963d0dc63ca838dfd48072c..74a639f9126185a750b62f30092eefa616b099a0 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/services/WhiteboardService.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/services/WhiteboardService.as @@ -66,10 +66,6 @@ package org.bigbluebutton.modules.whiteboard.services } } - public function sendText(e:WhiteboardDrawEvent):void { - sender.sendText(e); - } - public function sendShape(e:WhiteboardDrawEvent):void { sender.sendShape(e); } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/PencilDrawListener.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/PencilDrawListener.as index 416ef7970dde57d0cf5eb6973cd4bdd3b7d6c2ac..1f33a8ef95c9101d86cf2a6363dc40900af6757f 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/PencilDrawListener.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/PencilDrawListener.as @@ -38,10 +38,12 @@ package org.bigbluebutton.modules.whiteboard.views private var _sendFrequency:int; private var _shapeFactory:ShapeFactory; private var _ctrlKeyDown:Boolean = false; - private var _idGenerator:AnnotationIDGenerator; - private var _curID:String; - private var _wbModel:WhiteboardModel; - + private var _idGenerator:AnnotationIDGenerator; + private var _curID:String; + private var _wbModel:WhiteboardModel; + private var _wbId:String = null; + + public function PencilDrawListener(idGenerator:AnnotationIDGenerator, wbCanvas:WhiteboardCanvas, sendShapeFrequency:int, @@ -66,6 +68,8 @@ package org.bigbluebutton.modules.whiteboard.views _isDrawing = true; _drawStatus = DrawObject.DRAW_START; + _wbId = _wbModel.getCurrentWhiteboardId(); + // Generate a shape id so we can match the mouse down and up events. Then we can // remove the specific shape when a mouse up occurs. _curID = _idGenerator.generateID(); @@ -132,8 +136,12 @@ package org.bigbluebutton.modules.whiteboard.views var an:Annotation = dobj.createAnnotation(_wbModel, _ctrlKeyDown); + if (_wbId != null) { + an.annotation["whiteboardId"] = _wbId; + } + if (an != null) { - _wbCanvas.sendGraphicToServer(an, WhiteboardDrawEvent.SEND_SHAPE); + _wbCanvas.sendGraphicToServer(an); } } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/ShapeDrawListener.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/ShapeDrawListener.as index 8daf878171d68147d07192d0d606b6f366b9e038..a5a361140912ab50dd929c58497edd4461a48daa 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/ShapeDrawListener.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/ShapeDrawListener.as @@ -41,6 +41,7 @@ package org.bigbluebutton.modules.whiteboard.views private var _idGenerator:AnnotationIDGenerator; private var _curID:String; private var _wbModel:WhiteboardModel; + private var _wbId:String = null; public function ShapeDrawListener(idGenerator:AnnotationIDGenerator, wbCanvas:WhiteboardCanvas, @@ -67,6 +68,8 @@ package org.bigbluebutton.modules.whiteboard.views _isDrawing = true; _drawStatus = DrawObject.DRAW_START; + _wbId = _wbModel.getCurrentWhiteboardId(); + // Generate a shape id so we can match the mouse down and up events. Then we can // remove the specific shape when a mouse up occurs. _curID = _idGenerator.generateID(); @@ -129,8 +132,13 @@ package org.bigbluebutton.modules.whiteboard.views dobj.id = _curID; var an:Annotation = dobj.createAnnotation(_wbModel, _ctrlKeyDown); + + if (_wbId != null) { + an.annotation["whiteboardId"] = _wbId; + } + if (an != null) { - _wbCanvas.sendGraphicToServer(an, WhiteboardDrawEvent.SEND_SHAPE); + _wbCanvas.sendGraphicToServer(an); } } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/TextDrawListener.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/TextDrawListener.as index 93c56dd64506c6efda6ec45ca70855d505989e11..a44049f3be8802a80f4b357c0acb237d5bef0878 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/TextDrawListener.as +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/TextDrawListener.as @@ -17,9 +17,9 @@ * */ package org.bigbluebutton.modules.whiteboard.views { + import org.bigbluebutton.modules.whiteboard.business.shapes.DrawObject; import org.bigbluebutton.modules.whiteboard.business.shapes.ShapeFactory; import org.bigbluebutton.modules.whiteboard.business.shapes.TextDrawAnnotation; - import org.bigbluebutton.modules.whiteboard.business.shapes.TextObject; import org.bigbluebutton.modules.whiteboard.business.shapes.WhiteboardConstants; import org.bigbluebutton.modules.whiteboard.events.WhiteboardDrawEvent; import org.bigbluebutton.modules.whiteboard.models.WhiteboardModel; @@ -32,8 +32,6 @@ package org.bigbluebutton.modules.whiteboard.views { private var _shapeFactory:ShapeFactory; - private var _textStatus:String = TextObject.TEXT_CREATED; - private var _mouseXDown:Number = 0; private var _mouseYDown:Number = 0; @@ -50,6 +48,8 @@ package org.bigbluebutton.modules.whiteboard.views { private var _mousedDown:Boolean = false; + private var _wasEditing:Boolean = false; + private var _curID:String; private var feedback:RectangleFeedbackTextBox = new RectangleFeedbackTextBox(); @@ -77,6 +77,11 @@ package org.bigbluebutton.modules.whiteboard.views { // dispatched when the mouse goes out of the canvas, theu we end up sending a new text // even if the user has mousedDown yet. _mousedDown = true; + + // Need to check whether we were editing on mouse down because the edit will be finished by the time mouse up happens + _wasEditing = _wbCanvas.isEditingText(); + + _wbCanvas.addRawChild(feedback); } } @@ -85,12 +90,7 @@ package org.bigbluebutton.modules.whiteboard.views { _mouseXMove = mouseX; _mouseYMove = mouseY; - if (_wbCanvas.contains(feedback)) { - _wbCanvas.removeRawChild(feedback); - } - feedback.draw(_mouseXDown, _mouseYDown, mouseX - _mouseXDown, mouseY - _mouseYDown); - _wbCanvas.addRawChild(feedback); } } @@ -109,7 +109,7 @@ package org.bigbluebutton.modules.whiteboard.views { var tbWidth:Number = Math.abs(_mouseXMove - _mouseXDown); var tbHeight:Number = Math.abs(_mouseYMove - _mouseYDown); - if (tbHeight == 0 && tbWidth == 0 && !_wbCanvas.finishedTextEdit) { + if (tbHeight == 0 && tbWidth == 0 && !_wasEditing) { tbWidth = _singleClickWidth; tbHeight = _singleClickHeight; if (_mouseXDown + _singleClickWidth > _wbCanvas.width || _mouseYDown + _singleClickHeight > _wbCanvas.height) { @@ -120,32 +120,20 @@ package org.bigbluebutton.modules.whiteboard.views { return; } - var tobj:TextDrawAnnotation = _shapeFactory.createTextObject("", 0x000000, Math.min(_mouseXDown, _mouseXMove), Math.min(_mouseYDown, _mouseYMove), tbWidth, tbHeight, 18); + var tobj:TextDrawAnnotation = _shapeFactory.createTextAnnotation("", 0x000000, Math.min(_mouseXDown, _mouseXMove), Math.min(_mouseYDown, _mouseYMove), tbWidth, tbHeight, 18); - sendTextToServer(TextObject.TEXT_CREATED, tobj); + sendTextToServer(DrawObject.DRAW_START, tobj); } } private function sendTextToServer(status:String, tobj:TextDrawAnnotation):void { - switch (status) { - case TextObject.TEXT_CREATED: - tobj.status = TextObject.TEXT_CREATED; - _textStatus = TextObject.TEXT_UPDATED; - _curID = _idGenerator.generateID(); - tobj.id = _curID; - break; - case TextObject.TEXT_UPDATED: - tobj.status = TextObject.TEXT_UPDATED; - tobj.id = _curID; - break; - case TextObject.TEXT_PUBLISHED: - tobj.status = TextObject.TEXT_PUBLISHED; - _textStatus = TextObject.TEXT_CREATED; - tobj.id = _curID; - break; + if (status == DrawObject.DRAW_START) { + _curID = _idGenerator.generateID(); } + tobj.status = status; + tobj.id = _curID; - _wbCanvas.sendGraphicToServer(tobj.createAnnotation(_wbModel), WhiteboardDrawEvent.SEND_TEXT); + _wbCanvas.sendGraphicToServer(tobj.createAnnotation(_wbModel)); } } } diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/TextObjectListener.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/TextObjectListener.as deleted file mode 100755 index e1ffaa6e9e5b2635e71d3ce9bf6fa6c4f9178f45..0000000000000000000000000000000000000000 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/TextObjectListener.as +++ /dev/null @@ -1,32 +0,0 @@ -/** - * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ - * - * Copyright (c) 2012 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 com.asfusion.mate.events.Dispatcher; - - public class TextObjectListener - { - private var _dispatcher:Dispatcher; - - public function TextObjectListener(dispatcher:Dispatcher) - { - _dispatcher = dispatcher; - } - } -} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/TextUpdateListener.as b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/TextUpdateListener.as new file mode 100755 index 0000000000000000000000000000000000000000..1bdce5239dd99ad1e7530c281406832b0ca8f264 --- /dev/null +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/TextUpdateListener.as @@ -0,0 +1,123 @@ +package org.bigbluebutton.modules.whiteboard.views { + import flash.events.Event; + import flash.events.FocusEvent; + import flash.events.KeyboardEvent; + import flash.ui.Keyboard; + + import org.bigbluebutton.modules.whiteboard.business.shapes.DrawObject; + import org.bigbluebutton.modules.whiteboard.business.shapes.GraphicFactory; + import org.bigbluebutton.modules.whiteboard.business.shapes.ShapeFactory; + import org.bigbluebutton.modules.whiteboard.business.shapes.TextDrawAnnotation; + import org.bigbluebutton.modules.whiteboard.business.shapes.TextObject; + import org.bigbluebutton.modules.whiteboard.events.WhiteboardDrawEvent; + import org.bigbluebutton.modules.whiteboard.models.Annotation; + import org.bigbluebutton.modules.whiteboard.models.WhiteboardModel; + + public class TextUpdateListener { + private var _whiteboardCanvas:WhiteboardCanvas; + private var _whiteboardModel:WhiteboardModel; + private var _shapeFactory:ShapeFactory; + + private var _currentTextObject:TextObject; + private var _whiteboardId:String; + + public function TextUpdateListener() { + } + + public function setDependencies(whiteboardCanvas:WhiteboardCanvas, whiteboardModel:WhiteboardModel, shapeFactory:ShapeFactory):void { + _whiteboardCanvas = whiteboardCanvas; + _whiteboardModel = whiteboardModel; + _shapeFactory = shapeFactory; + } + + public function canvasMouseDown():void { + /** + * Check if the presenter is starting a new text annotation without committing the last one. + * If so, publish the last text annotation. + */ + if (needToPublish()) { + sendTextToServer(DrawObject.DRAW_END, _currentTextObject); + } + } + + private function needToPublish():Boolean { + return _currentTextObject != null && _currentTextObject.status != DrawObject.DRAW_END; + } + + public function isEditingText():Boolean { + return needToPublish(); + } + + public function newTextObject(tobj:TextObject):void { + _currentTextObject = tobj; + _whiteboardId = _whiteboardModel.getCurrentWhiteboardId(); + _whiteboardCanvas.textToolbar.syncPropsWith(_currentTextObject); + _whiteboardCanvas.stage.focus = tobj; + tobj.registerListeners(textObjLostFocusListener, textObjTextChangeListener, textObjKeyDownListener); + } + + public function removedTextObject(tobj:TextObject):void { + if (tobj == _currentTextObject) { + _currentTextObject = null; + _whiteboardCanvas.textToolbar.syncPropsWith(null); + tobj.deregisterListeners(textObjLostFocusListener, textObjTextChangeListener, textObjKeyDownListener); + } + } + + private function textObjLostFocusListener(event:FocusEvent):void { + // LogUtil.debug("### LOST FOCUS "); + // The presenter is moving the mouse away from the textbox. Perhaps to change the size and color of the text. + // Maintain focus to this textbox until the presenter does mouse down on the whiteboard canvas. + maintainFocusToTextBox(event); + } + + private function textObjTextChangeListener(event:Event):void { + // The text is being edited. Notify others to update the text. + var sendStatus:String = DrawObject.DRAW_UPDATE; + var tf:TextObject = event.target as TextObject; + sendTextToServer(sendStatus, tf); + } + + private function textObjKeyDownListener(event:KeyboardEvent):void { + // check for special conditions + if (event.keyCode == Keyboard.DELETE || event.keyCode == Keyboard.BACKSPACE || event.keyCode == Keyboard.ENTER) { + var sendStatus:String = DrawObject.DRAW_UPDATE; + var tobj:TextObject = event.target as TextObject; + sendTextToServer(sendStatus, tobj); + } + // stops stops page changing when trying to navigate the text box + if (event.keyCode == Keyboard.LEFT || event.keyCode == Keyboard.RIGHT) { + event.stopPropagation(); + } + } + + private function maintainFocusToTextBox(event:FocusEvent):void { + if (event.currentTarget == _currentTextObject) { + var tf:TextObject = event.currentTarget as TextObject; + if (_whiteboardCanvas.stage.focus != tf) _whiteboardCanvas.stage.focus = tf; + } + } + + private function sendTextToServer(status:String, tobj:TextObject):void { + if (status == DrawObject.DRAW_END) { + tobj.deregisterListeners(textObjLostFocusListener, textObjTextChangeListener, textObjKeyDownListener); + _currentTextObject = null; + _whiteboardCanvas.textToolbar.syncPropsWith(null); + } + + // LogUtil.debug("SENDING TEXT: [" + tobj.textSize + "]"); + var tda:TextDrawAnnotation = _shapeFactory.createTextAnnotation(tobj.text, tobj.textColor, tobj.x, tobj.y, tobj.width, tobj.height, tobj.fontSize); + + tda.status = status; + tda.id = tobj.id; + + var an:Annotation = tda.createAnnotation(_whiteboardModel); + + if (_whiteboardId != null) { + an.annotation["whiteboardId"] = _whiteboardId; + } + + _whiteboardCanvas.sendGraphicToServer(an); + } + } +} \ No newline at end of file diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardCanvas.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardCanvas.mxml index 1214ebb2512cfcf5640fb2d4d77e5c2eae63b230..ad554b90f9b158dc47ac60515672501f7d5adf0f 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardCanvas.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardCanvas.mxml @@ -34,7 +34,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. import org.bigbluebutton.modules.whiteboard.WhiteboardCanvasDisplayModel; import org.bigbluebutton.modules.whiteboard.WhiteboardCanvasModel; import org.bigbluebutton.modules.whiteboard.business.shapes.DrawObject; - import org.bigbluebutton.modules.whiteboard.business.shapes.TextObject; import org.bigbluebutton.modules.whiteboard.commands.GetWhiteboardAccessCommand; import org.bigbluebutton.modules.whiteboard.commands.GetWhiteboardShapesCommand; import org.bigbluebutton.modules.whiteboard.events.PageEvent; @@ -44,7 +43,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. public var model:WhiteboardCanvasModel; public var displayModel:WhiteboardCanvasDisplayModel; - public var finishedTextEdit : Boolean; public var textToolbar:WhiteboardTextToolbar; private var bbbCanvas:IBbbCanvas; @@ -52,15 +50,12 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. private var _yPosition:int; private var images:Images = new Images(); - [Bindable] private var select_icon:Class = images.select_icon; [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; [Bindable] private var ellipse_icon:Class = images.circle_icon; [Bindable] private var line_icon:Class = images.line_icon; [Bindable] private var text_icon:Class = images.text_icon; - [Bindable] private var eraser_icon:Class = images.eraser_icon; - [Bindable] private var highlighter_icon:Class = images.highlighter_icon; private var toolType:String = DrawObject.PENCIL; private var whiteboardEnabled:Boolean = false; private var showWhiteboard:Boolean = true; @@ -107,10 +102,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. stage.removeEventListener(MouseEvent.MOUSE_MOVE, doMouseMove); } - private function doMouseDown(event:Event):void { - finishedTextEdit = displayModel.needToPublish(); - displayModel.doMouseDown(this.mouseX, this.mouseY); + private function doMouseDown(event:Event):void { model.doMouseDown(this.mouseX, this.mouseY); + displayModel.doMouseDown(this.mouseX, this.mouseY); event.stopPropagation(); // we want to stop the bubbling so slide doesn't move stage.addEventListener(MouseEvent.MOUSE_UP, doMouseUp); @@ -120,21 +114,18 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. private function doMouseMove(event:Event):void { model.doMouseMove(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 setShape(s:String):void { -// LogUtil.debug("SET SHAPE [" + s + "]"); -// model.setShape(s); - } public function changeColor(e:Event):void { model.changeColor(e.target.selectedColor); } - + + public function isEditingText():Boolean { + return displayModel.isEditingText(); + } - public function sendGraphicToServer(gobj:Annotation, type:String):void { + public function sendGraphicToServer(gobj:Annotation):void { // LogUtil.debug("DISPATCHING SEND sendGraphicToServer [" + type + "]"); - var event:WhiteboardDrawEvent = new WhiteboardDrawEvent(type); + var event:WhiteboardDrawEvent = new WhiteboardDrawEvent(WhiteboardDrawEvent.SEND_SHAPE); event.annotation = gobj; var dispatcher:Dispatcher = new Dispatcher(); dispatcher.dispatchEvent(event); @@ -151,22 +142,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. toolType = s; } - public function changeFillColor(e:Event):void { -// model.changeFillColor(e.target.selectedColor); - } - public function changeThickness(e:Event):void { model.changeThickness(e.target.value); } - public function toggleFill():void { -// model.toggleFill(); - } - - public function toggleTransparency():void { -// model.toggleTransparency(); - } - public function get xPosition():int { return _xPosition; } @@ -183,11 +162,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. _yPosition = y; } - public function modifySelectedTextObject(fgColor:uint, bgColorVisible:Boolean, backgroundColor:uint, textSize:Number):void { -// LogUtil.debug("modifying text size = " + textSize); - displayModel.modifySelectedTextObject(fgColor, bgColorVisible, backgroundColor, textSize); - } - private function setWhiteboardVisibility():void { if (this.whiteboardEnabled && this.showWhiteboard) { this.visible = true; @@ -214,11 +188,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. CursorManager.setCursor(pencil_icon, 2, 0, -16); } else if(toolType == DrawObject.LINE) { CursorManager.setCursor(line_icon, 2, 0, -14); - } else if(toolType == DrawObject.HIGHLIGHTER) { - CursorManager.setCursor(highlighter_icon); - } else if(toolType == DrawObject.ERASER) { - CursorManager.setCursor(eraser_icon); - } else if(toolType == TextObject.TEXT_TOOL) { + } else if(toolType == DrawObject.TEXT) { CursorManager.setCursor(text_icon); // } else if(toolType == SelectObject.SELECT_TOOL) { // CursorManager.setCursor(select_icon); diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardTextToolbar.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardTextToolbar.mxml index c214c37eae6e172bd1cab285749d461693087879..32dd4e8064d0aeb9ff187041c5b8d30fb9a62e26 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardTextToolbar.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardTextToolbar.mxml @@ -29,9 +29,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. <mate:Listener type="{MadePresenterEvent.SWITCH_TO_VIEWER_MODE}" method="viewerMode" /> <mate:Listener type="{WhiteboardButtonEvent.DISABLE_WHITEBOARD}" method="disableTextToolbar" /> <mate:Listener type="{StopWhiteboardModuleEvent.STOP_HIGHLIGHTER_MODULE_EVENT}" method="closeToolbar" /> - <mate:Listener type="{GraphicObjectFocusEvent.OBJECT_SELECTED}" method="handleObjSelected" /> - <mate:Listener type="{GraphicObjectFocusEvent.OBJECT_DESELECTED}" method="handleObjDeselected" /> - <mx:Script> <![CDATA[ import mx.events.MoveEvent; @@ -39,11 +36,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. import org.as3commons.logging.api.ILogger; import org.as3commons.logging.api.getClassLogger; - import org.bigbluebutton.common.Images; import org.bigbluebutton.main.events.MadePresenterEvent; import org.bigbluebutton.modules.present.ui.views.PresentationWindow; import org.bigbluebutton.modules.whiteboard.business.shapes.TextObject; - import org.bigbluebutton.modules.whiteboard.events.GraphicObjectFocusEvent; import org.bigbluebutton.modules.whiteboard.events.StopWhiteboardModuleEvent; import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent; import org.bigbluebutton.util.i18n.ResourceUtil; @@ -55,8 +50,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. public var textSize:Number; public var backgroundVisible:Boolean; - private var images:Images = new Images(); - [Bindable] private var toggle_text_background_icon:Class = images.toggle_text_background_icon; private var currentlySelectedTextObject:TextObject = null; private var presentationWindow:PresentationWindow; private var normalAlpha:Number = 0.55; @@ -66,7 +59,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. public function init():void { this.alpha = normalAlpha; - this.visible = true; this.addEventListener(MouseEvent.ROLL_OVER, makeFocused); this.addEventListener(MouseEvent.ROLL_OUT, makeDim); @@ -102,31 +94,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. protected function setTextColor(e:Event):void{ enableTextToolbar(); this.textColor = e.target.selectedColor; - canvas.modifySelectedTextObject(textColor, backgroundVisible, bgColor, textSize); - canvas.stage.focus = currentlySelectedTextObject; - } - - /** - * Sets the background color of the selected text object - * @param e The event - * - */ - protected function changeTextBackgroundColor(e:Event):void{ - enableTextToolbar(); - this.bgColor = e.target.selectedColor; - canvas.modifySelectedTextObject(textColor, backgroundVisible, bgColor, textSize); - canvas.stage.focus = currentlySelectedTextObject; - } - - /** - * Sets the background color visible of the selected text object - * @param e The event - * - */ - protected function setBackgroundVisible(e:Event):void{ - enableTextToolbar(); - this.backgroundVisible = e.target.selected; - canvas.modifySelectedTextObject(textColor, backgroundVisible, bgColor, textSize); + currentlySelectedTextObject.applyNewFormat(textColor, textSize); canvas.stage.focus = currentlySelectedTextObject; } @@ -138,8 +106,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. protected function setTextSize(size:Number):void { enableTextToolbar(); this.textSize = size; - LOGGER.debug("Text size set to: " + size); - canvas.modifySelectedTextObject(textColor, backgroundVisible, bgColor, textSize); + currentlySelectedTextObject.applyNewFormat(textColor, textSize); } private function viewerMode(e:MadePresenterEvent):void{ @@ -151,7 +118,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. callLater(repositionToolbarByWindow); } - private function disableTextToolbar(evt:Event=null):void{ + private function disableTextToolbar(e:Event=null):void{ this.visible = false; } @@ -159,14 +126,18 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. parent.removeChild(this); } - public function syncPropsWith(tobj:TextObject):void{ - if(tobj == null) return; + public function syncPropsWith(tobj:TextObject):void { currentlySelectedTextObject = tobj; - this.textColor = ctextpik.selectedColor = tobj.textColor; -// this.bgColor = cbackpik.selectedColor = tobj.backgroundColor; -// this.backgroundVisible = btnToggleBackground.selected = tobj.background; - this.textSizeMenu.selectedItem = String(tobj.textSize); - this.textSize = tobj.textSize; + + if(tobj != null) { + enableTextToolbar(); + repositionToolbar(); + this.textColor = ctextpik.selectedColor = tobj.textColor; + this.textSizeMenu.selectedItem = String(tobj.fontSize); + this.textSize = tobj.fontSize; + } else { + disableTextToolbar(); + } } // invoked by WhiteboardManager when the TextToolbar is first loaded @@ -175,29 +146,18 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. presentationWindow.addEventListener(ResizeEvent.RESIZE, repositionToolbarByWindow); presentationWindow.addEventListener(MouseEvent.CLICK, repositionToolbarByWindow); presentationWindow.addEventListener(MoveEvent.MOVE, repositionToolbarByWindow); - disableTextToolbar(); - this.x = 0; - this.y = 0; - parent.setChildIndex(this, parent.numChildren-1); } /* required for repositioning the TextToolbar when an event occurs on the presentation window */ public function repositionToolbarByWindow(event:Event = null):void { - if (this.visible) { - if (currentlySelectedTextObject == null) { - return; - } - repositionToolbar(); - } + repositionToolbar(); } - public function repositionToolbar(tobj:TextObject = null):void { - if (this.visible) { + public function repositionToolbar():void { + if (this.visible && currentlySelectedTextObject) { // translate TextObject's coords to stage coords because TextToolbar is added to stage - - if (tobj == null) tobj = currentlySelectedTextObject; - - var loc:Point = canvas.localToGlobal(new Point(tobj.x, tobj.y)); + + var loc:Point = canvas.localToGlobal(new Point(currentlySelectedTextObject.x, currentlySelectedTextObject.y)); this.x = loc.x; this.y = loc.y - this.height - 45; parent.setChildIndex(this, parent.numChildren-1); @@ -206,32 +166,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. // repositions the toolbar when canvas is zoomed public function adjustForZoom(x:Number, y:Number):void { - if(currentlySelectedTextObject == null) return; - repositionToolbar(currentlySelectedTextObject); - } - - private function handleObjSelected(event:GraphicObjectFocusEvent):void { -// LogUtil.debug("###### handleObjSelected"); -// if(event.data.id != WhiteboardConstants.TYPE_TEXT) return; - var tobj:TextObject = event.data as TextObject; - syncPropsWith(tobj); - repositionToolbar(tobj); - enableTextToolbar(); - } - - private function handleObjDeselected(event:GraphicObjectFocusEvent):void { -// LogUtil.debug("##### handleObjDeselected"); -// if(event.data.id != WhiteboardConstants.TYPE_TEXT) return; - var tobj:TextObject = event.data as TextObject; - - /* checks if the new focus of the stage is not the TextToolbar, and if not, - hide the text toolbar. This is to prevent the TextToolbar from disappearing as - soon as the user changes focus. - */ - if (!containsFocus(this)) { - disableTextToolbar(); - textSizeMenu.close(); - } + repositionToolbar(); } /* used to check whether or not the TextToolbar and its children have focus when diff --git a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardToolbar.mxml b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardToolbar.mxml index 12b72a42b923e46d67cc51d69218b738ab5f1ced..db02555f6051a0fbe5b0d47804f87462ba03c2ad 100755 --- a/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardToolbar.mxml +++ b/bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardToolbar.mxml @@ -38,11 +38,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. <mate:Listener type="{WhiteboardPresenterEvent.MODIFIED_WHITEBOARD_ACCESS}" method="whiteboardAccessModified" /> <mate:Listener type="{StopWhiteboardModuleEvent.STOP_HIGHLIGHTER_MODULE_EVENT}" method="closeToolbar" /> <mate:Listener type="{ShortcutEvent.UNDO_WHITEBOARD}" method="undoShortcut" /> - <mate:Listener type="{GraphicObjectFocusEvent.OBJECT_SELECTED}" method="graphicObjSelected" /> - <mate:Listener type="{GraphicObjectFocusEvent.OBJECT_DESELECTED}" method="graphicObjDeselected" /> <mate:Listener type="{WhiteboardButtonEvent.WHITEBOARD_BUTTON_PRESSED}" method="handleWhiteboardButtonPressed"/> <mate:Listener type="{ChangeMyRole.CHANGE_MY_ROLE_EVENT}" method="refreshRole" /> - <mate:Listener type="{NavigationEvent.GOTO_PAGE}" method="handleSlideChange" /> <mate:Listener type="{DisplaySlideEvent.DISPLAY_SLIDE_EVENT}" method="handleSlideLoaded" /> <mate:Listener type="{UploadEvent.PRESENTATION_READY}" method="handlePresentationSwitch" /> <mate:Listener type="{PresenterStatusEvent.ANNOTATIONS_PERMISSION_CHANGE}" method="handleEnableAnnotations" /> @@ -83,13 +80,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. import org.bigbluebutton.main.events.ShortcutEvent; import org.bigbluebutton.main.model.users.events.ChangeMyRole; import org.bigbluebutton.modules.present.events.DisplaySlideEvent; - import org.bigbluebutton.modules.present.events.NavigationEvent; import org.bigbluebutton.modules.present.events.UploadEvent; import org.bigbluebutton.modules.present.model.Presenter; import org.bigbluebutton.modules.present.ui.views.PresentationWindow; import org.bigbluebutton.modules.whiteboard.business.shapes.GraphicObject; import org.bigbluebutton.modules.whiteboard.business.shapes.WhiteboardConstants; - import org.bigbluebutton.modules.whiteboard.events.GraphicObjectFocusEvent; import org.bigbluebutton.modules.whiteboard.events.StopWhiteboardModuleEvent; import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent; import org.bigbluebutton.modules.whiteboard.events.WhiteboardDrawEvent; @@ -98,24 +93,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. import org.bigbluebutton.util.i18n.ResourceUtil; private var images:Images = new Images(); - [Bindable] private var hand_icon:Class = images.hand_icon; - [Bindable] private var pencil_icon:Class = images.pencil_icon; - [Bindable] private var undo_icon:Class = images.undo_icon; - [Bindable] private var delete_icon:Class = images.delete_icon; - [Bindable] private var rectangle_icon:Class = images.square_icon; - [Bindable] private var ellipse_icon:Class = images.circle_icon; [Bindable] private var thick_icon:Class = images.whiteboard_thick; [Bindable] private var thin_icon:Class = images.whiteboard_thin; - [Bindable] private var scribble_icon:Class = images.scribble_icon; - [Bindable] private var text_icon:Class = images.text_icon; - [Bindable] private var triangle_icon:Class = images.triangle_icon; - [Bindable] private var line_icon:Class = images.line_icon; - [Bindable] private var fill_icon:Class = images.fill_icon; - [Bindable] private var transparency_icon:Class = images.transparency_icon; - [Bindable] private var eraser_icon:Class = images.eraser_icon; - [Bindable] private var highlighter_icon:Class = images.highlighter_icon; - [Bindable] private var select_icon:Class = images.select_icon; - [Bindable] private var grid_icon:Class = images.grid_icon; [Bindable] public var wbOptions:WhiteboardOptions = new WhiteboardOptions(); @@ -194,10 +173,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. canvas.changeColor(e); } - protected function changeFillColor(e:Event):void { - canvas.changeFillColor(e); - } - protected function changeThickness(e:Event):void { canvas.changeThickness(e); } @@ -211,14 +186,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. event.multiUser = !multiUser; dispatcher.dispatchEvent(event); } - - protected function toggleFill():void { - canvas.toggleFill(); - } - - protected function toggleTransparency():void { - canvas.toggleTransparency(); - } private function presenterMode(e:MadePresenterEvent):void { checkVisibility(); @@ -330,12 +297,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. checkVisibility(); } - private function handleSlideChange(e:NavigationEvent):void { - slideLoaded = false; - // don't switch the toolbar button on slide change - checkVisibility(); - } - private function handlePresentationSwitch(e:UploadEvent):void { slideLoaded = false; if (panzoomBtn) { @@ -343,14 +304,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. } checkVisibility(); } - - private function graphicObjSelected(event:GraphicObjectFocusEvent):void { - var gobj:GraphicObject = event.data; - } - - private function graphicObjDeselected(event:GraphicObjectFocusEvent):void { - var gobj:GraphicObject = event.data; - } private function toolbarAllowed():Boolean { return (multiUser? true : isPresenter);