Merge branch '090-change-role' into mconf-live0.6.1

Conflicts:
	bigbluebutton-apps/src/main/java/org/bigbluebutton/conference/service/participants/ParticipantsApplication.java
	bigbluebutton-apps/src/main/java/org/bigbluebutton/conference/service/participants/ParticipantsService.java
	bigbluebutton-client/src/org/bigbluebutton/common/Images.as
	bigbluebutton-client/src/org/bigbluebutton/modules/users/maps/UsersMainEventMap.mxml
	bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageReceiver.as
	bigbluebutton-client/src/org/bigbluebutton/modules/users/services/MessageSender.as
	bigbluebutton-client/src/org/bigbluebutton/modules/videoconf/views/ToolbarButton.mxml
	bigbluebutton-client/src/org/bigbluebutton/modules/whiteboard/views/WhiteboardToolbar.mxml
This commit is contained in:
Felipe Cecagno 2014-11-23 21:58:27 -02:00
commit 8caa85f333
50 changed files with 994 additions and 478 deletions

View File

@ -49,6 +49,7 @@ public class MessagingConstants {
public static final String USER_JOINED_EVENT = "UserJoinedEvent";
public static final String USER_LEFT_EVENT = "UserLeftEvent";
public static final String USER_STATUS_CHANGE_EVENT = "UserStatusChangeEvent";
public static final String USER_ROLE_CHANGE_EVENT = "UserRoleChangeEvent";
public static final String SEND_POLLS_EVENT = "SendPollsEvent";
public static final String RECORD_STATUS_EVENT = "RecordStatusEvent";
}

View File

@ -114,4 +114,8 @@ public class ParticipantsApplication {
public void kickGuest(String meetingId, String guestId) {
bbbInGW.kickGuest(meetingId, guestId);
}
public void setParticipantRole(String meetingId, String userId, String role) {
bbbInGW.setUserRole(meetingId, userId, role);
}
}

View File

@ -141,4 +141,12 @@ public class ParticipantsService {
String roomName = Red5.getConnectionLocal().getScope().getName();
application.kickGuest(roomName, guestId);
}
public void setParticipantRole(Map<String, String> msg) {
String roomName = Red5.getConnectionLocal().getScope().getName();
String userId = (String) msg.get("userId");
String role = (String) msg.get("role");
log.debug("Setting participant role " + roomName + " " + userId + " " + role);
application.setParticipantRole(roomName, userId, role);
}
}

View File

@ -0,0 +1,35 @@
/**
* 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.conference.service.recorder.participants;
public class ParticipantRoleChangeRecordEvent extends AbstractParticipantRecordEvent {
public ParticipantRoleChangeRecordEvent() {
super();
setEvent("ParticipantRoleChangeEvent");
}
public void setUserId(String userId) {
eventMap.put("userId", userId);
}
public void setRole(String role) {
eventMap.put("role", role);
}
}

View File

@ -34,6 +34,7 @@ public interface IBigBlueButtonInGW {
void shareWebcam(String meetingId, String userId, String stream);
void unshareWebcam(String meetingId, String userId, String stream);
void setUserStatus(String meetingID, String userID, String status, Object value);
void setUserRole(String meetingID, String userID, String role);
void getUsers(String meetingID, String requesterID);
void userLeft(String meetingID, String userID);
void userJoin(String meetingID, String userID);

View File

@ -156,6 +156,11 @@ class BigBlueButtonInGW(bbbGW: BigBlueButtonGateway, presUtil: PreuploadedPresen
bbbGW.accept(new ChangeUserStatus(meetingID, userID, status, value));
}
def setUserRole(meetingID: String, userID: String, role: String) {
val userRole = if (role == "MODERATOR") Role.MODERATOR else Role.VIEWER
bbbGW.accept(new ChangeUserRole(meetingID, userID, userRole));
}
def getUsers(meetingID: String, requesterID: String):Unit = {
bbbGW.accept(new GetUsers(meetingID, requesterID))
}

View File

@ -45,6 +45,7 @@ class CollectorActor(dispatcher: IDispatcher) extends Actor {
case msg: UserShareWebcam => handleUserShareWebcam(msg)
case msg: UserUnshareWebcam => handleUserUnshareWebcam(msg)
case msg: ChangeUserStatus => handleChangeUserStatus(msg)
case msg: ChangeUserRole => handleChangeUserRole(msg)
case msg: AssignPresenter => handleAssignPresenter(msg)
case msg: SetRecordingStatus => handleSetRecordingStatus(msg)
case msg: GetChatHistoryRequest => handleGetChatHistoryRequest(msg)
@ -135,6 +136,7 @@ class CollectorActor(dispatcher: IDispatcher) extends Actor {
case msg: UserSharedWebcam => handleUserSharedWebcam(msg)
case msg: UserUnsharedWebcam => handleUserUnsharedWebcam(msg)
case msg: UserStatusChange => handleUserStatusChange(msg)
case msg: UserRoleChange => handleUserRoleChange(msg)
case msg: MuteVoiceUser => handleMuteVoiceUser(msg)
case msg: UserVoiceMuted => handleUserVoiceMuted(msg)
case msg: UserVoiceTalking => handleUserVoiceTalking(msg)
@ -570,6 +572,21 @@ class CollectorActor(dispatcher: IDispatcher) extends Actor {
dispatcher.dispatch(buildJson(header, payload))
}
private def handleChangeUserRole(msg: ChangeUserRole) {
val payload = new java.util.HashMap[String, Any]()
payload.put(Constants.MEETING_ID, msg.meetingID)
payload.put(Constants.USER_ID, msg.userID)
payload.put(Constants.ROLE, msg.role)
val header = new java.util.HashMap[String, Any]()
header.put(Constants.NAME, MessageNames.CHANGE_USER_ROLE)
header.put(Constants.TIMESTAMP, TimestampGenerator.generateTimestamp)
header.put(Constants.CURRENT_TIME, TimestampGenerator.getCurrentTime)
// println("***** DISPATCHING CHANGE USER ROLE *****************")
dispatcher.dispatch(buildJson(header, payload))
}
private def handleAssignPresenter(msg: AssignPresenter) {
val payload = new java.util.HashMap[String, Any]()
payload.put(Constants.MEETING_ID, msg.meetingID)
@ -1716,6 +1733,22 @@ class CollectorActor(dispatcher: IDispatcher) extends Actor {
dispatcher.dispatch(buildJson(header, payload))
}
private def handleUserRoleChange(msg: UserRoleChange) {
val payload = new java.util.HashMap[String, Any]()
payload.put(Constants.MEETING_ID, msg.meetingID)
payload.put(Constants.RECORDED, msg.recorded)
payload.put(Constants.USER_ID, msg.userID)
payload.put(Constants.ROLE, msg.role)
val header = new java.util.HashMap[String, Any]()
header.put(Constants.NAME, MessageNames.USER_ROLE_CHANGED)
header.put(Constants.TIMESTAMP, TimestampGenerator.generateTimestamp)
header.put(Constants.CURRENT_TIME, TimestampGenerator.getCurrentTime)
// println("***** DISPATCHING USER ROLE CHANGE *****************")
dispatcher.dispatch(buildJson(header, payload))
}
private def handleMuteVoiceUser(msg: MuteVoiceUser) {
val payload = new java.util.HashMap[String, Any]()
payload.put(Constants.MEETING_ID, msg.meetingID)

View File

@ -62,6 +62,7 @@ class MeetingActor(val meetingID: String, val meetingName: String, val recorded:
case msg: AssignPresenter => handleAssignPresenter(msg)
case msg: GetUsers => handleGetUsers(msg)
case msg: ChangeUserStatus => handleChangeUserStatus(msg)
case msg: ChangeUserRole => handleChangeUserRole(msg)
case msg: EjectUserFromMeeting => handleEjectUserFromMeeting(msg)
case msg: UserRaiseHand => handleUserRaiseHand(msg)
case msg: UserLowerHand => handleUserLowerHand(msg)

View File

@ -139,6 +139,12 @@ case class ChangeUserStatus(
value: Object
) extends InMessage
case class ChangeUserRole(
meetingID: String,
userID: String,
role: Role
) extends InMessage
case class AssignPresenter(
meetingID: String,
newPresenterID: String,

View File

@ -23,6 +23,7 @@ object MessageNames {
val USER_SHARE_WEBCAM = "user_share_webcam_request"
val USER_UNSHARE_WEBCAM = "user_unshare_webcam_request"
val CHANGE_USER_STATUS = "change_user_status_request"
val CHANGE_USER_ROLE = "change_user_role_request"
val ASSIGN_PRESENTER = "assign_presenter_request"
val SET_RECORDING_STATUS = "set_recording_status_request"
val GET_CHAT_HISTORY = "get_chat_history_request"
@ -115,6 +116,7 @@ object MessageNames {
val USER_SHARED_WEBCAM = "user_shared_webcam_message"
val USER_UNSHARED_WEBCAM = "user_unshared_webcam_message"
val USER_STATUS_CHANGED = "user_status_changed_message"
val USER_ROLE_CHANGED = "user_role_changed_message"
val MUTE_VOICE_USER = "mute_voice_user_request"
val USER_VOICE_MUTED = "user_voice_muted_message"
val USER_VOICE_TALKING = "user_voice_talking_message"

View File

@ -261,6 +261,14 @@ case class UserStatusChange(
version:String = Versions.V_0_0_1
) extends IOutMessage
case class UserRoleChange(
meetingID: String,
recorded: Boolean,
userID: String,
role: String,
version:String = Versions.V_0_0_1
) extends IOutMessage
case class MuteVoiceUser(
meetingID: String,
recorded: Boolean,

View File

@ -226,6 +226,15 @@ trait UsersApp {
}
}
def handleChangeUserRole(msg: ChangeUserRole) {
users.getUser(msg.userID) foreach {user =>
val uvo = user.copy(role=msg.role)
users.addUser(uvo)
val userRole = if(msg.role == Role.MODERATOR) "MODERATOR" else "VIEWER"
outGW.send(new UserRoleChange(meetingID, recorded, msg.userID, userRole))
}
}
def handleGetUsers(msg: GetUsers):Unit = {
// Filter out guests waiting
val approvedUsers = users.getUsers.filter(x => !guestsWaiting.contains(x.userID))

View File

@ -27,6 +27,7 @@ class UsersClientMessageSender(service: ConnectionInvokerService) extends OutMes
case msg: JoinMeetingReply => handleJoinMeetingReply(msg)
case msg: UserLeft => handleUserLeft(msg)
case msg: UserStatusChange => handleUserStatusChange(msg)
case msg: UserRoleChange => handleUserRoleChange(msg)
case msg: UserRaisedHand => handleUserRaisedHand(msg)
case msg: UserLoweredHand => handleUserLoweredHand(msg)
case msg: UserSharedWebcam => handleUserSharedWebcam(msg)
@ -463,7 +464,22 @@ class UsersClientMessageSender(service: ConnectionInvokerService) extends OutMes
var m = new BroadcastClientMessage(msg.meetingID, "participantStatusChange", message);
service.sendMessage(m);
}
private def handleUserRoleChange(msg: UserRoleChange) {
var args = new HashMap[String, Object]();
args.put("userID", msg.userID);
args.put("role", msg.role);
val message = new java.util.HashMap[String, Object]()
val gson = new Gson();
message.put("msg", gson.toJson(args))
// println("UsersClientMessageSender - handleUserRoleChange \n" + message.get("msg") + "\n")
var m = new BroadcastClientMessage(msg.meetingID, "participantRoleChange", message);
service.sendMessage(m);
}
private def handleUserListeningOnly(msg: UserListeningOnly) {
var args = new HashMap[String, Object]();
args.put("userId", msg.userID);

View File

@ -30,6 +30,7 @@ class UsersEventRedisPublisher(service: MessageSender) extends OutMessageListene
case msg: UserSharedWebcam => handleUserSharedWebcam(msg)
case msg: UserUnsharedWebcam => handleUserUnsharedWebcam(msg)
case msg: UserStatusChange => handleUserStatusChange(msg)
case msg: UserRoleChange => handleUserRoleChange(msg)
case msg: UserVoiceMuted => handleUserVoiceMuted(msg)
case msg: UserVoiceTalking => handleUserVoiceTalking(msg)
case msg: MuteVoiceUser => handleMuteVoiceUser(msg)
@ -91,7 +92,12 @@ class UsersEventRedisPublisher(service: MessageSender) extends OutMessageListene
val json = UsersMessageToJsonConverter.userStatusChangeToJson(msg)
service.send(MessagingConstants.FROM_USERS_CHANNEL, json)
}
private def handleUserRoleChange(msg: UserRoleChange) {
val json = UsersMessageToJsonConverter.userRoleChangeToJson(msg)
service.send(MessagingConstants.FROM_USERS_CHANNEL, json)
}
private def handleUserRaisedHand(msg: UserRaisedHand) {
val json = UsersMessageToJsonConverter.userRaisedHandToJson(msg)
service.send(MessagingConstants.FROM_USERS_CHANNEL, json)

View File

@ -187,6 +187,16 @@ object UsersMessageToJsonConverter {
val header = Util.buildHeader(MessageNames.USER_STATUS_CHANGED, msg.version, None)
Util.buildJson(header, payload)
}
def userRoleChangeToJson(msg: UserRoleChange):String = {
val payload = new java.util.HashMap[String, Any]()
payload.put(Constants.MEETING_ID, msg.meetingID)
payload.put(Constants.USER_ID, msg.userID)
payload.put(Constants.ROLE, msg.role)
val header = Util.buildHeader(MessageNames.USER_ROLE_CHANGED, msg.version, None)
Util.buildJson(header, payload)
}
def userSharedWebcamToJson(msg: UserSharedWebcam):String = {
val payload = new java.util.HashMap[String, Any]()

View File

@ -160,6 +160,8 @@ bbb.users.usersGrid.mediaItemRenderer.webcam = Webcam shared
bbb.users.usersGrid.mediaItemRenderer.micOff = Microphone off
bbb.users.usersGrid.mediaItemRenderer.micOn = Microphone on
bbb.users.usersGrid.mediaItemRenderer.noAudio = Not in audio conference
bbb.users.usersGrid.mediaItemRenderer.promoteUser = Promote {0} to moderator
bbb.users.usersGrid.mediaItemRenderer.demoteUser = Demote {0} to viewer
bbb.presentation.title = Presentation
bbb.presentation.titleWithPres = Presentation: {0}
bbb.presentation.quickLink.label = Presentation Window

View File

@ -157,6 +157,8 @@ bbb.users.usersGrid.mediaItemRenderer.webcam = Webcam sendo transmitida
bbb.users.usersGrid.mediaItemRenderer.micOff = Microfone desativado
bbb.users.usersGrid.mediaItemRenderer.micOn = Microfone ativado
bbb.users.usersGrid.mediaItemRenderer.noAudio = Não está na conferência de voz
bbb.users.usersGrid.mediaItemRenderer.promoteUser = Promover {0} para moderador
bbb.users.usersGrid.mediaItemRenderer.demoteUser = Despromover {0} para participante
bbb.presentation.title = Apresentação
bbb.presentation.titleWithPres = Apresentação\: {0}
bbb.presentation.quickLink.label = Janela de apresentação

View File

@ -318,5 +318,11 @@ package org.bigbluebutton.common
[Embed(source="assets/images/presenter_white.png")]
public var presenter_white:Class;
[Embed(source="assets/images/user_add.png")]
public var user_add:Class;
[Embed(source="assets/images/user_delete.png")]
public var user_delete:Class;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 B

View File

@ -159,9 +159,12 @@ package org.bigbluebutton.main.model.users
}
public function set role(r:String):void {
_role = r;
moderator = _role == MODERATOR;
verifyUserStatus();
}
[Bindable] public var moderator:Boolean = false;
[Bindable] public var room:String = "";
[Bindable] public var authToken:String = "";
[Bindable] public var selected:Boolean = false;

View File

@ -437,7 +437,16 @@ package org.bigbluebutton.main.model.users {
users.refresh();
}
public function newUserRole(userID:String, role:String):void {
var aUser:BBBUser = getUser(userID);
if (aUser != null) {
aUser.role = role;
}
users.refresh();
}
public function getUserIDs():ArrayCollection {
var uids:ArrayCollection = new ArrayCollection();
for (var i:int = 0; i < users.length; i++) {

View File

@ -47,6 +47,7 @@ package org.bigbluebutton.main.model.users
import org.bigbluebutton.main.model.ConferenceParameters;
import org.bigbluebutton.main.model.users.events.BroadcastStartedEvent;
import org.bigbluebutton.main.model.users.events.BroadcastStoppedEvent;
import org.bigbluebutton.main.model.users.events.ChangeRoleEvent;
import org.bigbluebutton.main.model.users.events.ConferenceCreatedEvent;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.main.model.users.events.LowerHandEvent;
@ -278,6 +279,10 @@ package org.bigbluebutton.main.model.users
public function kickUser(e:KickUserEvent):void{
if (this.isModerator()) sender.kickUser(e.userid);
}
public function changeRole(e:ChangeRoleEvent):void {
if (this.isModerator()) sender.changeRole(e.userid, e.role);
}
/**
* Assign a new presenter

View File

@ -0,0 +1,35 @@
/**
* 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.main.model.users.events
{
import flash.events.Event;
public class ChangeMyRole extends Event
{
public static const CHANGE_MY_ROLE_EVENT:String = "CHANGE_MY_ROLE_EVENT";
public var role:String;
public function ChangeMyRole(role:String)
{
this.role = role;
super(CHANGE_MY_ROLE_EVENT, true, false);
}
}
}

View File

@ -0,0 +1,37 @@
/**
* 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.main.model.users.events
{
import flash.events.Event;
public class ChangeRoleEvent extends Event
{
public static const CHANGE_ROLE_EVENT:String = "CHANGE_ROLE_EVENT";
public var userid:String;
public var role:String;
public function ChangeRoleEvent(userid:String, role:String)
{
this.userid = userid;
this.role = role;
super(CHANGE_ROLE_EVENT, true, false);
}
}
}

View File

@ -37,6 +37,7 @@ $Id: $
<mate:Listener type="{LocaleChangeEvent.LOCALE_CHANGED}" method="localeChanged" />
<mate:Listener type="{ShortcutEvent.MUTE_ME_EVENT}" method="toggleMuteMeState" />
<mate:Listener type="{EventConstants.USER_TALKING}" method="handleUserTalking" />
<mate:Listener type="{ChangeMyRole.CHANGE_MY_ROLE_EVENT}" method="refreshRole" />
<mate:Listener type="{LockControlEvent.CHANGED_LOCK_SETTINGS}" method="lockSettingsChanged" />
<mate:Listener type="{BBBEvent.USER_VOICE_JOINED}" method="handleJoinedVoiceConferenceEvent" />
<mate:Listener type="{BBBEvent.USER_VOICE_LEFT}" method="handleLeftVoiceConferenceEvent" />
@ -59,6 +60,7 @@ $Id: $
import org.bigbluebutton.main.events.ShortcutEvent;
import org.bigbluebutton.main.model.users.BBBUser;
import org.bigbluebutton.main.model.users.Conference;
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
import org.bigbluebutton.util.i18n.ResourceUtil;
private static const LOG:String = "Main::View::MuteMeButton - ";
@ -85,6 +87,10 @@ $Id: $
private function localeChanged(e:Event):void {
updateMuteMeBtn();
}
private function refreshRole(e:ChangeMyRole):void {
updateMuteMeBtn();
}
private function lockSettingsChanged(e:Event):void {
if (UsersUtil.amIModerator() || UsersUtil.amIPresenter()){
@ -114,7 +120,7 @@ $Id: $
var conference:Conference = userManager.getConference();
var me:BBBUser = conference.getMyUser();
// trace(LOG + "allowMuteUnmute [ voiceJoined=[" + conference.voiceJoined + "], disableMic=[" + me.disableMyMic + "]");
return (conference.voiceJoined && !me.disableMyMic);
return (conference.voiceJoined && (!me.disableMyMic || me.moderator));
}
private function updateMuteMeBtn(placeholder:Boolean = false):void {

View File

@ -26,7 +26,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
creationComplete="init()">
<mate:Listener type="{LockControlEvent.CHANGED_LOCK_SETTINGS}" method="lockSettingsChanged" />
<mate:Listener type="{ChangeMyRole.CHANGE_MY_ROLE_EVENT}" method="refreshRole" />
<mx:Script>
<![CDATA[
import com.asfusion.mate.events.Dispatcher;
@ -42,6 +43,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.main.model.users.BBBUser;
import org.bigbluebutton.main.model.users.Conference;
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
import org.bigbluebutton.modules.chat.events.ChatOptionsEvent;
import org.bigbluebutton.modules.chat.model.ChatOptions;
import org.bigbluebutton.util.i18n.ResourceUtil;
@ -94,16 +96,20 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
private function lockSettingsChanged(e:Event):void {
if (UsersUtil.amIModerator() || UsersUtil.amIPresenter()) return; // Settings only affect viewers.
var userManager:UserManager = UserManager.getInstance();
var conference:Conference = userManager.getConference();
var me:BBBUser = conference.getMyUser();
usersList.enabled = !me.disableMyPrivateChat;
refreshListStatus();
}
private function refreshRole(e:ChangeMyRole):void {
refreshListStatus();
}
private function refreshListStatus():void {
var userManager:UserManager = UserManager.getInstance();
var conference:Conference = userManager.getConference();
var me:BBBUser = conference.getMyUser();
usersList.enabled = !me.disableMyPrivateChat || me.moderator || me.presenter;
}
]]>
</mx:Script>

View File

@ -63,6 +63,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<mate:Listener type="{ShortcutEvent.CHAT_DEBUG}" method="chatDebugInfo" />
<mate:Listener type="{LockControlEvent.CHANGED_LOCK_SETTINGS}" method="lockSettingsChanged" />
<mate:Listener type="{ChangeMyRole.CHANGE_MY_ROLE_EVENT}" method="refreshRole" />
<mx:Script>
<![CDATA[
@ -81,6 +82,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.main.events.UserLeftEvent;
import org.bigbluebutton.main.model.users.BBBUser;
import org.bigbluebutton.main.model.users.Conference;
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
import org.bigbluebutton.modules.chat.ChatConstants;
import org.bigbluebutton.modules.chat.ChatUtil;
import org.bigbluebutton.modules.chat.events.ChatOptionsEvent;
@ -95,7 +97,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.modules.chat.views.ChatMessageRenderer;
import org.bigbluebutton.modules.chat.vo.ChatMessageVO;
import org.bigbluebutton.util.i18n.ResourceUtil;
private static const LOG:String = "Chat::ChatBox - ";
public var publicChat:Boolean = false;
@ -624,20 +626,25 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
applyLockSettings();
}
private function applyLockSettings():void {
if (UsersUtil.amIModerator() || UsersUtil.amIPresenter()) return; // Settings only affect viewers.
var userManager:UserManager = UserManager.getInstance();
var conference:Conference = userManager.getConference();
var me:BBBUser = conference.getMyUser();
if (publicChat) {
txtMsgArea.enabled = sendBtn.enabled = !me.disableMyPublicChat;
} else {
txtMsgArea.enabled = sendBtn.enabled = !me.disableMyPrivateChat;
}
private function applyLockSettings():void {
updateChat();
}
private function updateChat():void {
var userManager:UserManager = UserManager.getInstance();
var conference:Conference = userManager.getConference();
var me:BBBUser = conference.getMyUser();
if (publicChat) {
txtMsgArea.enabled = sendBtn.enabled = !me.disableMyPublicChat || me.moderator || me.presenter;
} else {
txtMsgArea.enabled = sendBtn.enabled = !me.disableMyPrivateChat || me.moderator || me.presenter;
}
}
private function refreshRole(e:ChangeMyRole):void {
updateChat();
}
]]>
</mx:Script>

View File

@ -24,6 +24,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import mx.events.FlexEvent;
import org.bigbluebutton.core.EventConstants;
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
import org.bigbluebutton.main.events.MadePresenterEvent;
import org.bigbluebutton.modules.layout.events.ChangeLayoutEvent;
import org.bigbluebutton.modules.layout.events.ComboBoxCreatedEvent;
@ -62,7 +63,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<EventHandlers type="{LayoutEvent.STOP_LAYOUT_MODULE_EVENT}">
<MethodInvoker generator="{LayoutEventMapDelegate}" method="stopModule" />
</EventHandlers>
<EventHandlers type="{ChangeMyRole.CHANGE_MY_ROLE_EVENT}">
<MethodInvoker generator="{LayoutEventMapDelegate}" method="refreshRole" arguments="{event}"/>
</EventHandlers>
<EventHandlers type="{LayoutEvent.APPLY_DEFAULT_LAYOUT_EVENT}">
<MethodInvoker generator="{LayoutManager}" method="applyDefaultLayout" />
</EventHandlers>
@ -141,4 +146,4 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<PropertyInjector targetKey="sender" source="{MessageSender}"/>
</Injectors>
</EventMap>
</EventMap>

View File

@ -24,13 +24,16 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import com.asfusion.mate.events.Dispatcher;
import org.bigbluebutton.common.LogUtil;
import org.bigbluebutton.common.Role;
import org.bigbluebutton.common.events.ToolbarButtonEvent;
import org.bigbluebutton.main.model.LayoutOptions;
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
import org.bigbluebutton.modules.layout.views.ToolbarComponent;
private var _attributes:Object;
private var _globalDispatcher:Dispatcher = new Dispatcher();
private var options:LayoutOptions = new LayoutOptions();
private var layoutComponent:ToolbarComponent;
public function stopModule():void {
}
@ -39,7 +42,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
_attributes = attributes;
options.parseOptions();
var layoutComponent:ToolbarComponent = new ToolbarComponent();
layoutComponent = new ToolbarComponent();
// using the negation will keep it enabled if the property is not there
layoutComponent.enableEdit = !(_attributes.enableEdit == "false");
@ -50,6 +53,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
_globalDispatcher.dispatchEvent(event);
}
public function refreshRole(e:ChangeMyRole):void {
layoutComponent.enableEdit = !(_attributes.enableEdit == "false");
layoutComponent.refreshRole(e.role == Role.MODERATOR);
}
]]>
</mx:Script>
</EventMap>

View File

@ -50,6 +50,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
_dispatcher.dispatchEvent(new LayoutEvent(LayoutEvent.ADD_CURRENT_LAYOUT_EVENT));
}
public function refreshRole(amIModerator:Boolean):void {
this.enabled = amIModerator;
}
]]>
</mx:Script>
</views:LayoutButton>

View File

@ -24,8 +24,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
xmlns:views="org.bigbluebutton.modules.layout.views.*"
toolTip="{ResourceUtil.getInstance().getString('bbb.layout.broadcastButton.toolTip')}"
icon="{_icon}"
click="onClick(event)"
enabled="{UserManager.getInstance().getConference().amIModerator()}">
click="onClick(event)">
<mx:Script>
<![CDATA[
@ -45,14 +44,16 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
[Bindable] private var _icon:Class = _images.page_link;
private function init():void {
if (!UserManager.getInstance().getConference().amIModerator()) {
this.visible = false;
}
refreshRole(UserManager.getInstance().getConference().amIModerator());
}
private function onClick(e:Event):void {
_dispatcher.dispatchEvent(new LayoutEvent(LayoutEvent.BROADCAST_LAYOUT_EVENT));
}
public function refreshRole(amIModerator:Boolean):void {
this.visible = this.includeInLayout = this.enabled = amIModerator;
}
]]>
</mx:Script>
</views:LayoutButton>

View File

@ -85,6 +85,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
trace(LOG + "initing");
dataProvider = layoutNames;
populateComboBox();
refreshRole(UsersUtil.amIModerator());
}
private function lockSettingsChanged(e:LockControlEvent):void {
@ -144,7 +145,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
private function onSelectedItemChanged(e:Event):void {
_dispatcher.dispatchEvent(new ChangeLayoutEvent(e.currentTarget.selectedItem.localeKey));
}
public function refreshRole(amIModerator:Boolean):void {
var layoutLocked:Boolean = UserManager.getInstance().getConference().getLockSettings().getLockedLayout();
this.enabled = amIModerator || !layoutLocked;
}
]]>
</mx:Script>
</mx:ComboBox>

View File

@ -50,6 +50,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
_dispatcher.dispatchEvent(new LayoutEvent(LayoutEvent.LOAD_LAYOUTS_EVENT));
}
public function refreshRole(amIModerator:Boolean):void {
this.enabled = amIModerator;
}
]]>
</mx:Script>
</views:LayoutButton>

View File

@ -49,9 +49,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
[Bindable] private var icon_unlocked:Class = _images.unlocked;
private function init():void {
if (!UserManager.getInstance().getConference().amIModerator()) {
this.visible = false;
}
refreshRole(UserManager.getInstance().getConference().amIModerator());
}
private function onClick(e:Event):void {
@ -73,6 +71,15 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
this.selected = false;
this.setStyle("icon", icon_unlocked);
}
public function refreshRole(amIModerator:Boolean):void {
this.enabled = amIModerator;
if (amIModerator) {
this.visible = true;
} else {
this.visible = this.selected;
}
}
]]>
</mx:Script>
</views:LayoutButton>

View File

@ -50,6 +50,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
_dispatcher.dispatchEvent(new LayoutEvent(LayoutEvent.SAVE_LAYOUTS_EVENT));
}
public function refreshRole(amIModerator:Boolean):void {
this.enabled = amIModerator;
}
]]>
</mx:Script>
</views:LayoutButton>

View File

@ -48,6 +48,16 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
public function set enableEdit(arg:Boolean):void {
_enableEdit = arg && UserManager.getInstance().getConference().amIModerator();
}
public function refreshRole(amIModerator:Boolean):void {
comboBox.refreshRole(amIModerator);
//lockButton.refreshRole(amIModerator);
addButton.refreshRole(amIModerator);
saveButton.refreshRole(amIModerator);
loadButton.refreshRole(amIModerator);
broadcastButton.refreshRole(amIModerator);
}
public function set visibleTools(arg:Boolean):void {
_visibleTools = arg;
@ -91,10 +101,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
visible="{_enableEdit}"
tabIndex="{baseIndex+3}"/>
<views:BroadcastButton id="broadcastButton"
tabIndex="{baseIndex+4}"
enabled="{!lockButton.selected}"/>
<views:LockButton id="lockButton"
tabIndex="{baseIndex+4}"/>
<!-- <views:LockButton id="lockButton"
tabIndex="{baseIndex+5}"
visible="false"
includeInLayout="false"/>
-->
</mx:HBox>

View File

@ -39,6 +39,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.main.model.users.UserService;
import org.bigbluebutton.main.model.users.events.BroadcastStartedEvent;
import org.bigbluebutton.main.model.users.events.BroadcastStoppedEvent;
import org.bigbluebutton.main.model.users.events.ChangeRoleEvent;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.main.model.users.events.LowerHandEvent;
import org.bigbluebutton.main.model.users.events.RaiseHandEvent;
@ -95,6 +96,14 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<MethodInvoker generator="{UserService}" method="changeRecordingStatus" arguments="{event}" />
</EventHandlers>
<EventHandlers type="{KickUserEvent.KICK_USER}" >
<MethodInvoker generator="{UserService}" method="kickUser" arguments="{event}" />
</EventHandlers>
<EventHandlers type="{ChangeRoleEvent.CHANGE_ROLE_EVENT}" >
<MethodInvoker generator="{UserService}" method="changeRole" arguments="{event}" />
</EventHandlers>
<EventHandlers type="{VoiceConfEvent.EJECT_USER}" >
<MethodInvoker generator="{UserService}" method="ejectUser" arguments="{event}" />
</EventHandlers>

View File

@ -45,6 +45,7 @@ package org.bigbluebutton.modules.users.services
import org.bigbluebutton.main.model.users.BBBUser;
import org.bigbluebutton.main.model.users.Conference;
import org.bigbluebutton.main.model.users.IMessageListener;
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
import org.bigbluebutton.main.model.users.events.UsersConnectionEvent;
import org.bigbluebutton.modules.present.events.CursorEvent;
@ -98,6 +99,9 @@ package org.bigbluebutton.modules.users.services
case "participantStatusChange":
handleParticipantStatusChange(message);
break;
case "participantRoleChange":
handleParticipantRoleChange(message);
break;
case "userJoinedVoice":
handleUserJoinedVoice(message);
break;
@ -596,6 +600,17 @@ package org.bigbluebutton.modules.users.services
}
}
public function handleParticipantRoleChange(msg:Object):void {
var map:Object = JSON.parse(msg.msg);
trace(LOG + "*** received participant role change [" + map.userID + "," + map.role + "]");
UserManager.getInstance().getConference().newUserRole(map.userID, map.role);
if(UserManager.getInstance().getConference().amIThisUser(map.userID)) {
UserManager.getInstance().getConference().setMyRole(map.role);
var e:ChangeMyRole = new ChangeMyRole(map.role);
dispatcher.dispatchEvent(e);
}
}
public function handleGuestRequestedToEnter(msg:Object):void {
trace(LOG + "*** handleRequestedToEnter " + msg.msg + " **** \n");
var map:Object = JSON.parse(msg.msg);

View File

@ -359,6 +359,24 @@ package org.bigbluebutton.modules.users.services
);
}
public function changeRole(userID:String, role:String):void {
var _nc:ConnectionManager = BBB.initConnectionManager();
var message:Object = new Object();
message["userId"] = userID;
message["role"] = role;
_nc.sendMessage(
"participants.setParticipantRole",// Remote function name
function(result:String):void { // On successful result
LogUtil.debug(result);
},
function(status:String):void { // status - On error occurred
LogUtil.error(status);
},
message
);
}
public function queryForGuestPolicy():void {
trace(LOG + "queryForGuestPolicy");
var _nc:ConnectionManager = BBB.initConnectionManager();

View File

@ -28,6 +28,7 @@
<mate:Listener type="{UsersRollEvent.USER_ROLL_OVER}" method="onRollOver" />
<mate:Listener type="{UsersRollEvent.USER_ROLL_OUT}" method="onRollOut" />
<mate:Listener type="{ChangeMyRole.CHANGE_MY_ROLE_EVENT}" method="onChangeMyRole" />
<mx:Script>
<![CDATA[
@ -35,8 +36,10 @@
import mx.binding.utils.BindingUtils;
import mx.controls.Alert;
import mx.controls.Menu;
import mx.events.FlexEvent;
import mx.events.ListEvent;
import mx.events.MenuEvent;
import org.bigbluebutton.common.Images;
import org.bigbluebutton.common.LogUtil;
@ -44,10 +47,11 @@
import org.bigbluebutton.core.events.LockControlEvent;
import org.bigbluebutton.core.events.VoiceConfEvent;
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.main.events.BBBEvent;
import org.bigbluebutton.main.events.StoppedViewingWebcamEvent;
import org.bigbluebutton.main.model.users.BBBUser;
import org.bigbluebutton.main.model.users.Conference;
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
import org.bigbluebutton.main.model.users.events.ChangeRoleEvent;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.main.model.users.events.LowerHandEvent;
import org.bigbluebutton.modules.users.events.UsersRollEvent;
@ -70,8 +74,10 @@
private var options:UsersOptions;
private var myMenu:Menu = null;
private function onCreationComplete():void{
lockBtn.enabled = muteBtn.enabled = kickUserBtn.enabled = moderator = UserManager.getInstance().getConference().amIModerator();
refreshRole(UserManager.getInstance().getConference().amIModerator());
this.addEventListener(FlexEvent.DATA_CHANGE, dataChangeHandler);
@ -105,7 +111,20 @@
updateButtons();
}
}
private function onChangeMyRole(e:ChangeMyRole):void {
rolledOver = false;
updateButtons();
// close the menu if it was opened
if (myMenu) myMenu.hide();
refreshRole(e.role == Role.MODERATOR);
}
private function refreshRole(amIModerator:Boolean):void {
lockBtn.enabled = muteBtn.enabled = settingsBtn.enabled = moderator = amIModerator;
}
private function muteMouseOverHandler():void {
rolledOverMute = true;
updateButtons();
@ -159,8 +178,7 @@
muteImg.filters = null;
if (data != null) {
kickUserBtn.visible = !data.me && rolledOver && options.allowKickUser;
settingsBtn.visible = rolledOver && !data.me;
if (!data.voiceJoined) {
if (data.listenOnly) {
@ -259,10 +277,73 @@
}
}
}
private function promoteUser():void {
changeUserRole(Role.MODERATOR);
}
private function demoteUser():void {
changeUserRole(Role.VIEWER);
}
private function changeUserRole(role:String):void {
var changeRoleEvent:ChangeRoleEvent = new ChangeRoleEvent(data.userID, role);
dispatchEvent(changeRoleEvent);
}
private function openSettings():void {
if (data != null) {
var myMenuData:Array = [];
if (data.role == Role.MODERATOR) {
myMenuData.push({
label: ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.demoteUser',[data.name]),
icon: images.user_delete,
callback: demoteUser
});
} else {
myMenuData.push({
label: ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.promoteUser',[data.name]),
icon: images.user_add,
callback: promoteUser
});
}
if (options.allowKickUser) {
myMenuData.push({
label: ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.kickUser',[data.name]),
icon: images.eject_user_new,
callback: kickUser
});
}
// make sure the previous menu is closed before opening a new one
// This could be improved to include a flag that tells if the menu is open,
// but it would require an extra listener for the MenuCloseEvent.
if (myMenu) myMenu.hide();
myMenu = Menu.createMenu(null, myMenuData, true);
myMenu.variableRowHeight = true;
var settingsBtnPos:Point = settingsBtn.localToGlobal(new Point(0,0));
var myMenuPos:Point = new Point();
myMenuPos.x = settingsBtnPos.x + settingsBtn.width;
myMenuPos.y = settingsBtnPos.y;
myMenu.addEventListener(MenuEvent.ITEM_CLICK, menuClickHandler);
myMenu.show(myMenuPos.x, myMenuPos.y);
myMenu.setFocus();
}
}
private function menuClickHandler(e:MenuEvent):void {
e.item.callback();
}
]]>
</mx:Script>
<!--mx:Image id="talkingIcon" visible="{data.talking}" source="{images.sound_new}" width="20" height="16"
toolTip="{ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.talking')}" /-->
<mx:Image id="webcamImg" visible="false" source="{images.webcam_new_20}"
@ -271,22 +352,22 @@
<mx:Button id="webcamBtn" visible="false" includeInLayout="false" icon="{images.webcam_new_20}"
width="20" height="20" enabled="true" click="viewCamera()"
toolTip="{ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.webcamBtn')}" />
<mx:Image id="muteImg" visible="false" includeInLayout="true" width="20" height="20" />
<mx:Image id="muteImg" visible="false" width="20" height="20" />
<mx:Button id="muteBtn" visible="false" includeInLayout="false" enabled="false" icon="{images.audio}"
width="20" height="20" click="toggleMuteState()"
mouseOver="muteMouseOverHandler()"
mouseOut="muteMouseOutHandler()"
toolTip="{data.voiceMuted ? ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.pushToTalk',[data.name]) : ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.pushToMute',[data.name])}" />
<mx:Button id="kickUserBtn" icon="{images.eject_user_new}"
width="20" height="20" visible="false"
toolTip="{ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.kickUser',[data.name])}"
click="kickUser()"/>
<mx:Image id="lockImg" visible="false" includeInLayout="false" width="20" height="20" />
<mx:Image id="lockImg" visible="false" width="20" height="20" />
<mx:Button id="lockBtn" visible="false" includeInLayout="false" enabled="false"
width="20" height="20" click="toggleLockState()"
mouseOver="lockMouseOverHandler()"
mouseOut="lockMouseOutHandler()"
toolTip="{data.userLocked ? ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.pushToUnlock',[data.name]) : ResourceUtil.getInstance().getString('bbb.users.usersGrid.mediaItemRenderer.pushToLock',[data.name])}" />
<mx:Button id="settingsBtn" visible="false"
width="20" height="20" click="openSettings()"
icon="{images.users_settings}"
toolTip="{ResourceUtil.getInstance().getString('bbb.users.settings.buttonTooltip')}" />
<!-- Helper objects because using BindingUtil with data break when the itemRenderer is recycled -->
<mx:Image id="muteInd" includeInLayout="false" visible="{data.voiceMuted}" />
<mx:Image id="voiceJoinedInd" includeInLayout="false" visible="{data.voiceJoined}" />

View File

@ -30,6 +30,7 @@
<mate:Listener type="{UsersRollEvent.USER_ROLL_OVER}" method="onRollOver" />
<mate:Listener type="{UsersRollEvent.USER_ROLL_OUT}" method="onRollOut" />
<mate:Listener type="{LocaleChangeEvent.LOCALE_CHANGED}" method="localeChanged" />
<mate:Listener type="{ChangeMyRole.CHANGE_MY_ROLE_EVENT}" method="onChangeMyRole" />
<mx:Script>
<![CDATA[
@ -42,6 +43,7 @@
import org.bigbluebutton.common.Role;
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.main.model.users.events.LowerHandEvent;
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
import org.bigbluebutton.modules.users.events.UsersRollEvent;
import org.bigbluebutton.util.i18n.ResourceUtil;
@ -51,7 +53,7 @@
private var moderator:Boolean = false;
private function onCreationComplete():void {
moderator = UserManager.getInstance().getConference().amIModerator();
refreshRole(UserManager.getInstance().getConference().amIModerator());
/* I was trying to the binds through actionscript, but every time the itemrenderer was recycled
* the binds would stop functioning. I think it might have been because I was using strong
@ -143,6 +145,17 @@
updateButton();
}
}
private function onChangeMyRole(e:ChangeMyRole):void {
rolledOver = false;
updateButton();
refreshRole(e.role == Role.MODERATOR);
}
private function refreshRole(amIModerator:Boolean):void {
moderator = amIModerator;
}
private function roleBtnClicked():void {
if (data.raiseHand) {

View File

@ -35,6 +35,7 @@
<mate:Listener type="{ShortcutEvent.MUTE_ALL_BUT_PRES}" method="remoteMuteAllButPres" />
<mate:Listener type="{MeetingMutedEvent.MEETING_MUTED}" method="handleMeetingMuted" />
<mate:Listener type="{LockControlEvent.CHANGED_LOCK_SETTINGS}" method="handleChangedLockSettingsEvent" />
<mate:Listener type="{ChangeMyRole.CHANGE_MY_ROLE_EVENT}" method="onChangeMyRole" />
<mx:Script>
<![CDATA[
import com.asfusion.mate.events.Dispatcher;
@ -59,6 +60,8 @@
import org.bigbluebutton.core.vo.LockSettingsVO;
import org.bigbluebutton.main.events.ShortcutEvent;
import org.bigbluebutton.main.model.users.BBBUser;
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
import org.bigbluebutton.main.model.users.events.ChangeRoleEvent;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.main.model.users.events.LowerHandEvent;
import org.bigbluebutton.main.model.users.events.RaiseHandEvent;
@ -104,14 +107,16 @@
private var muteMeRolled:Boolean = false;
private var myMenuData:Array = [];
private function onChangeMyRole(e:ChangeMyRole):void {
refreshRole(e.role == Role.MODERATOR);
}
private function onCreationComplete():void {
dispatcher = new Dispatcher();
users = UserManager.getInstance().getConference().users;
amIModerator = UserManager.getInstance().getConference().amIModerator();
settingsBtn.visible = settingsBtn.includeInLayout = partOptions.enableSettingsButton && amIModerator;
refreshRole(UserManager.getInstance().getConference().amIModerator());
BindingUtils.bindSetter(updateNumberofUsers, users, "length");
@ -137,6 +142,16 @@
usersGrid.addEventListener(MouseEvent.MOUSE_OVER, handleUsersGridMouseOver);
}
private function refreshRole(moderator:Boolean = true):void {
amIModerator = moderator;
settingsBtn.visible = settingsBtn.includeInLayout = partOptions.enableSettingsButton && amIModerator;
changeButtons(UserManager.getInstance().getConference().amIPresenter);
if (myMenu) myMenu.hide();
}
public function getPrefferedPosition():String{
return MainCanvas.TOP_LEFT;
}

View File

@ -22,6 +22,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
xmlns:mate="http://mate.asfusion.com/"
creationComplete="onCreationComplete()">
<mate:Listener type="{LockControlEvent.CHANGED_LOCK_SETTINGS}" method="lockSettingsChanged" />
<mate:Listener type="{ChangeMyRole.CHANGE_MY_ROLE_EVENT}" method="refreshRole" />
<mx:Script>
<![CDATA[
import com.asfusion.mate.events.Dispatcher;
@ -37,6 +38,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.main.model.users.BBBUser;
import org.bigbluebutton.main.model.users.Conference;
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
import org.bigbluebutton.main.model.users.events.KickUserEvent;
import org.bigbluebutton.main.model.users.events.RoleChangeEvent;
import org.bigbluebutton.modules.chat.model.ChatOptions;
@ -72,6 +74,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
muteUnmuteBtn.styleName = "videoUnmutedButtonStyle";
}
}
private function refreshRole(e:ChangeMyRole):void {
updateControlButtons();
}
public function updateControlButtons():void {
showControlButtons();

View File

@ -36,6 +36,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<mate:Listener type="{BBBEvent.CAM_SETTINGS_CLOSED}" method="handleCamSettingsClosedEvent"/>
<mate:Listener type="{ShareCameraRequestEvent.SHARE_CAMERA_REQUEST}" receive="enabled=false" />
<mate:Listener type="{LockControlEvent.CHANGED_LOCK_SETTINGS}" method="lockSettingsChanged" />
<mate:Listener type="{ChangeMyRole.CHANGE_MY_ROLE_EVENT}" method="refreshRole" />
<mx:Script>
<![CDATA[
@ -54,6 +55,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.main.events.ShortcutEvent;
import org.bigbluebutton.main.model.users.BBBUser;
import org.bigbluebutton.main.model.users.Conference;
import org.bigbluebutton.main.model.users.events.ChangeMyRole;
import org.bigbluebutton.main.views.MainToolbar;
import org.bigbluebutton.modules.videoconf.events.ClosePublishWindowEvent;
import org.bigbluebutton.modules.videoconf.events.ShareCameraRequestEvent;
@ -76,18 +78,20 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
private var dispatcher:Dispatcher;
public function lockSettingsChanged(e:*):void{
if (UsersUtil.amIModerator() || UsersUtil.amIPresenter()){
// Ignore lock setting changes as
// or presenter we are moderator.
return;
}
updateButton();
}
private function refreshRole(e:ChangeMyRole):void {
updateButton();
}
private function updateButton():void {
var userManager:UserManager = UserManager.getInstance();
var conference:Conference = userManager.getConference();
var me:BBBUser = conference.getMyUser();
this.visible = !me.disableMyCam;
this.includeInLayout = !me.disableMyCam;
this.visible = me.moderator || me.presenter || !me.disableMyCam;
this.includeInLayout = me.moderator || me.presenter || !me.disableMyCam;
}
private function init():void{

View File

@ -1,409 +1,415 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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/>.
-->
<mx:VBox xmlns="flexlib.containers.*"
initialize="init()"
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:view="org.bigbluebutton.modules.whiteboard.views.*"
xmlns:wbBtns="org.bigbluebutton.modules.whiteboard.views.buttons.*"
xmlns:mate="http://mate.asfusion.com/"
creationComplete="onCreationComplete()"
visible="{showWhiteboardToolbar}"
includeInLayout="{showWhiteboardToolbar}"
styleName="whiteboardToolbarStyle">
<mate:Listener type="{MadePresenterEvent.SWITCH_TO_PRESENTER_MODE}" method="presenterMode" />
<mate:Listener type="{MadePresenterEvent.SWITCH_TO_VIEWER_MODE}" method="viewerMode" />
<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="{NavigationEvent.GOTO_PAGE}" method="handleSlideChange" />
<mate:Listener type="{DisplaySlideEvent.DISPLAY_SLIDE_EVENT}" method="handleSlideLoaded" />
<mate:Listener type="{UploadEvent.PRESENTATION_READY}" method="handlePresentationSwitch" />
<mx:Style>
.colorPickerStyle {
backgroundColor:#E5E6E7;
columnCount:13;
horizontalGap:0;
previewHeight:22;
previewWidth:50;
swatchGridBackgroundColor:#000000;
swatchGridBorderSize:0;
swatchHeight:60;
swatchHighlightColor:#FFFFFF;
swatchHighlightSize:1;
swatchWidth:12;
textFieldWidth:72;
verticalGap:0;
}
</mx:Style>
<mx:Script>
<![CDATA[
import com.asfusion.mate.events.Listener;
import flash.ui.Keyboard;
import flexlib.mdi.events.MDIWindowEvent;
import mx.containers.ControlBar;
import mx.events.MoveEvent;
import mx.events.ResizeEvent;
import mx.managers.CursorManager;
import org.bigbluebutton.common.Images;
import org.bigbluebutton.common.LogUtil;
import org.bigbluebutton.core.UsersUtil;
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.main.events.MadePresenterEvent;
import org.bigbluebutton.main.events.ShortcutEvent;
import org.bigbluebutton.modules.present.events.DisplaySlideEvent;
import org.bigbluebutton.modules.present.events.PresentationEvent;
import org.bigbluebutton.modules.present.events.NavigationEvent;
import org.bigbluebutton.modules.present.events.UploadEvent;
import org.bigbluebutton.modules.present.ui.views.PresentationWindow;
import org.bigbluebutton.modules.present.ui.views.SlideView;
import org.bigbluebutton.modules.whiteboard.business.shapes.DrawObject;
import org.bigbluebutton.modules.whiteboard.business.shapes.GraphicObject;
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.StopWhiteboardModuleEvent;
import org.bigbluebutton.modules.whiteboard.events.ToggleGridEvent;
import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent;
import org.bigbluebutton.modules.whiteboard.events.WhiteboardDrawEvent;
import org.bigbluebutton.modules.whiteboard.events.WhiteboardPresenterEvent;
import org.bigbluebutton.modules.whiteboard.events.WhiteboardSettingResetEvent;
import org.bigbluebutton.modules.whiteboard.views.models.WhiteboardOptions;
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;
[Bindable] private var baseIndex:int;
[Bindable] private var showWhiteboardToolbar:Boolean = false;
private static const LOG:String = "WB::WhiteboardToolbar - ";
private var mousedOver:Boolean = false;
private var slideLoaded:Boolean = false;
public var canvas:WhiteboardCanvas;
private var presentationWindow:PresentationWindow;
[Bindable] private var colorPickerColours:Array = ['0x000000', '0xFFFFFF' , '0xFF0000', '0xFF8800',
'0xCCFF00', '0x00FF00', '0x00FF88', '0x00FFFF', '0x0088FF', '0x0000FF', '0x8800FF', '0xFF00FF', '0xC0C0C0'];
private function init():void{
wbOptions = new WhiteboardOptions();
baseIndex = wbOptions.baseTabIndex;
}
private function onCreationComplete():void {
setToolType(WhiteboardConstants.TYPE_ZOOM, null);
}
private function handleWhiteboardButtonPressed(e:WhiteboardButtonEvent):void {
setToolType(e.graphicType, e.toolType);
}
private function setToolType(graphicType:String, toolType:String):void {
if (graphicType == WhiteboardConstants.TYPE_CLEAR) {
dispatchEvent(new WhiteboardDrawEvent(WhiteboardDrawEvent.CLEAR));
} else if (graphicType == WhiteboardConstants.TYPE_UNDO) {
sendUndoCommand();
} else {
canvas.setGraphicType(graphicType);
canvas.setTool(toolType);
if (panzoomBtn != null) {
panzoomBtn.setTool(graphicType, toolType);
}
if (scribbleBtn != null) {
scribbleBtn.setTool(graphicType, toolType);
}
if (rectangleBtn != null) {
rectangleBtn.setTool(graphicType, toolType);
}
if (circleBtn != null) {
circleBtn.setTool(graphicType, toolType);
}
if (triangleBtn != null) {
triangleBtn.setTool(graphicType, toolType);
}
if (lineBtn != null) {
lineBtn.setTool(graphicType, toolType);
}
if (textBtn != null) {
textBtn.setTool(graphicType, toolType);
}
}
}
protected function changeColor(e:Event):void {
canvas.changeColor(e);
}
protected function changeFillColor(e:Event):void {
canvas.changeFillColor(e);
}
protected function changeThickness(e:Event):void {
canvas.changeThickness(e);
}
protected function toggleFill():void {
canvas.toggleFill();
}
protected function toggleTransparency():void {
canvas.toggleTransparency();
}
private function presenterMode(e:MadePresenterEvent):void {
if (canvas == null) return;
canvas.makeTextObjectsEditable(e);
setToolType(WhiteboardConstants.TYPE_ZOOM, null);
}
private function viewerMode(e:MadePresenterEvent):void {
canvas.makeTextObjectsUneditable(e);
if (!toolbarAllowed()) {
checkVisibility();
if (panzoomBtn) {
panzoomBtn.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
}
}
}
private function undoShortcut(e:ShortcutEvent):void{
trace(LOG + "Ctrl-Z got into undoShortcut");
sendUndoCommand();
}
private function sendUndoCommand():void {
// if (!canvas.isPageEmpty()) {
dispatchEvent(new WhiteboardDrawEvent(WhiteboardDrawEvent.UNDO));
// }
}
public function positionToolbar(window:PresentationWindow):void {
trace(LOG + "Positioning whiteboard toolbar");
presentationWindow = window;
presentationWindow.addEventListener(MoveEvent.MOVE, setPositionAndDepth);
presentationWindow.addEventListener(ResizeEvent.RESIZE, setPositionAndDepth);
presentationWindow.addEventListener(MouseEvent.CLICK, setPositionAndDepth);
if (!wbOptions.keepToolbarVisible) {
window.presCtrlBar.addEventListener(MouseEvent.ROLL_OVER, handleMouseOut);
window.presCtrlBar.addEventListener(MouseEvent.ROLL_OUT, handleMouseIn);
window.addEventListener(MouseEvent.ROLL_OVER, handleMouseIn);
window.addEventListener(MouseEvent.ROLL_OUT, handleMouseOut);
this.addEventListener(MouseEvent.ROLL_OVER, handleMouseIn);
this.addEventListener(MouseEvent.ROLL_OUT, handleMouseOut);
} else {
var listener1:Listener = new Listener();
listener1.method = checkVisibility;
listener1.type = MadePresenterEvent.SWITCH_TO_PRESENTER_MODE;
var listener2:Listener = new Listener();
listener2.method = checkVisibility;
listener2.type = MadePresenterEvent.SWITCH_TO_VIEWER_MODE;
//Do an initial check to see if the toolbar should be visible
checkVisibility();
}
}
private function checkVisibility(e:MadePresenterEvent = null):void {
if (toolbarAllowed() && slideLoaded && (wbOptions.keepToolbarVisible || mousedOver) && !presentationWindow.minimized) {
setPositionAndDepth();
showWhiteboardToolbar = true;
} else {
showWhiteboardToolbar = false;
}
}
private function setPositionAndDepth(e:Event = null):void {
this.x = presentationWindow.x + presentationWindow.width - 43;
this.y = presentationWindow.y + 30;
parent.setChildIndex(this, parent.numChildren - 1);
}
private function closeToolbar(e:StopWhiteboardModuleEvent):void {
parent.removeChild(this);
}
private function handleMouseIn(e:MouseEvent):void {
mousedOver = true;
checkVisibility();
}
private function handleMouseOut(e:MouseEvent = null):void {
mousedOver = false;
checkVisibility();
}
private function handleSlideLoaded(e:DisplaySlideEvent):void {
slideLoaded = true;
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) {
panzoomBtn.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
}
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 {
if (wbOptions) {
if (wbOptions.whiteboardAccess == "presenter")
return isPresenter;
else if (wbOptions.whiteboardAccess == "moderator")
return isModerator || isPresenter;
else if (wbOptions.whiteboardAccess == "all")
return true;
else
return false;
} else
return false;
}
/** Helper method to test whether this user is the presenter */
private function get isPresenter():Boolean {
return UsersUtil.amIPresenter();
}
private function get isModerator():Boolean {
return UsersUtil.amIModerator();
}
]]>
</mx:Script>
<!-- Now, every 'tool' has two types of identifiers, one is found in WhiteboardConstants
that identifies the "category" of the tool (ex. shape vs text), and the other specifies the
tool itself (ex. line tool vs triangle tool, even though both are "shapes")
-->
<wbBtns:PanZoomButton id="panzoomBtn"
tabIndex="{baseIndex}"
visible="{showWhiteboardToolbar}"/>
<mx:Spacer height="10" visible="{showWhiteboardToolbar}"/>
<wbBtns:ScribbleButton id="scribbleBtn"
tabIndex="{baseIndex+1}"
visible="{showWhiteboardToolbar}"/>
<wbBtns:RectangleButton id="rectangleBtn"
tabIndex="{baseIndex+2}"
visible="{showWhiteboardToolbar}"/>
<wbBtns:CircleButton id="circleBtn"
tabIndex="{baseIndex+3}"
visible="{showWhiteboardToolbar}"/>
<wbBtns:TriangleButton id="triangleBtn"
tabIndex="{baseIndex+4}"
visible="{showWhiteboardToolbar}"/>
<wbBtns:LineButton id="lineBtn"
tabIndex="{baseIndex+5}"
visible="{showWhiteboardToolbar}"/>
<wbBtns:TextButton id="textBtn"
tabIndex="{baseIndex+6}"
visible="{showWhiteboardToolbar}"/>
<mx:Spacer height="5" visible="{showWhiteboardToolbar}"/>
<wbBtns:ClearButton id="clearBtn"
tabIndex="{baseIndex+7}"
visible="{showWhiteboardToolbar}"/>
<wbBtns:UndoButton id="undoBtn"
tabIndex="{baseIndex+8}"
visible="{showWhiteboardToolbar}"/>
<mx:Spacer height="5" visible="{showWhiteboardToolbar}"/>
<!--
Properties that were removed from original color picker:
swatchPanelStyleName="colorPickerStyle"
dataProvider="{colorPickerColours}"
-->
<!-- Layout is really bad right now, and is confusing. Basically, there are two
of ColorPickers, one for the "line" color for the outlines of shapes, and the other for
the "fill" color that is used only if "fill" is enabled in WhiteboardCanvasModel
-->
<mx:ColorPicker change="changeColor(event)" id="cpik" visible="{showWhiteboardToolbar}"
selectedColor="0x000000" width="30" dataProvider="{colorPickerColours}" swatchPanelStyleName="colorPickerStyle"
toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.color')}"
tabIndex="{baseIndex+9}"
accessibilityName="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.color')}"/>
<mx:Spacer height="3" visible="{showWhiteboardToolbar}"/>
<mx:Image source="{thick_icon}" horizontalAlign="center" width="30" visible="{showWhiteboardToolbar}"/>
<mx:VSlider height="50" id="sld" change="changeThickness(event)" visible="{showWhiteboardToolbar}"
toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.thickness.accessibilityName')}"
minimum="1" maximum="30"
useHandCursor="true" value="2" showDataTip="true" snapInterval="1" dataTipOffset="0" labelOffset="0"
tabIndex="{baseIndex+10}"
accessibilityName="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.thickness.accessibilityName')}" />
<mx:Image source="{thin_icon}" horizontalAlign="center" width="30" visible="{showWhiteboardToolbar}"/>
</mx:VBox>
<?xml version="1.0" encoding="utf-8"?>
<!--
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/>.
-->
<mx:VBox xmlns="flexlib.containers.*"
initialize="init()"
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:view="org.bigbluebutton.modules.whiteboard.views.*"
xmlns:wbBtns="org.bigbluebutton.modules.whiteboard.views.buttons.*"
xmlns:mate="http://mate.asfusion.com/"
creationComplete="onCreationComplete()"
visible="{showWhiteboardToolbar}"
includeInLayout="{showWhiteboardToolbar}"
styleName="whiteboardToolbarStyle">
<mate:Listener type="{MadePresenterEvent.SWITCH_TO_PRESENTER_MODE}" method="presenterMode" />
<mate:Listener type="{MadePresenterEvent.SWITCH_TO_VIEWER_MODE}" method="viewerMode" />
<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" />
<mx:Style>
.colorPickerStyle {
backgroundColor:#E5E6E7;
columnCount:13;
horizontalGap:0;
previewHeight:22;
previewWidth:50;
swatchGridBackgroundColor:#000000;
swatchGridBorderSize:0;
swatchHeight:60;
swatchHighlightColor:#FFFFFF;
swatchHighlightSize:1;
swatchWidth:12;
textFieldWidth:72;
verticalGap:0;
}
</mx:Style>
<mx:Script>
<![CDATA[
import com.asfusion.mate.events.Listener;
import flash.ui.Keyboard;
import flexlib.mdi.events.MDIWindowEvent;
import mx.containers.ControlBar;
import mx.events.MoveEvent;
import mx.events.ResizeEvent;
import mx.managers.CursorManager;
import org.bigbluebutton.common.Images;
import org.bigbluebutton.common.LogUtil;
import org.bigbluebutton.core.UsersUtil;
import org.bigbluebutton.core.managers.UserManager;
import org.bigbluebutton.main.events.MadePresenterEvent;
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.PresentationEvent;
import org.bigbluebutton.modules.present.events.NavigationEvent;
import org.bigbluebutton.modules.present.events.UploadEvent;
import org.bigbluebutton.modules.present.ui.views.PresentationWindow;
import org.bigbluebutton.modules.present.ui.views.SlideView;
import org.bigbluebutton.modules.whiteboard.business.shapes.DrawObject;
import org.bigbluebutton.modules.whiteboard.business.shapes.GraphicObject;
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.StopWhiteboardModuleEvent;
import org.bigbluebutton.modules.whiteboard.events.ToggleGridEvent;
import org.bigbluebutton.modules.whiteboard.events.WhiteboardButtonEvent;
import org.bigbluebutton.modules.whiteboard.events.WhiteboardDrawEvent;
import org.bigbluebutton.modules.whiteboard.events.WhiteboardPresenterEvent;
import org.bigbluebutton.modules.whiteboard.events.WhiteboardSettingResetEvent;
import org.bigbluebutton.modules.whiteboard.views.models.WhiteboardOptions;
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;
[Bindable] private var baseIndex:int;
[Bindable] private var showWhiteboardToolbar:Boolean = false;
private static const LOG:String = "WB::WhiteboardToolbar - ";
private var mousedOver:Boolean = false;
private var slideLoaded:Boolean = false;
public var canvas:WhiteboardCanvas;
private var presentationWindow:PresentationWindow;
[Bindable] private var colorPickerColours:Array = ['0x000000', '0xFFFFFF' , '0xFF0000', '0xFF8800',
'0xCCFF00', '0x00FF00', '0x00FF88', '0x00FFFF', '0x0088FF', '0x0000FF', '0x8800FF', '0xFF00FF', '0xC0C0C0'];
private function init():void{
wbOptions = new WhiteboardOptions();
baseIndex = wbOptions.baseTabIndex;
}
private function onCreationComplete():void {
setToolType(WhiteboardConstants.TYPE_ZOOM, null);
}
private function handleWhiteboardButtonPressed(e:WhiteboardButtonEvent):void {
setToolType(e.graphicType, e.toolType);
}
private function setToolType(graphicType:String, toolType:String):void {
if (graphicType == WhiteboardConstants.TYPE_CLEAR) {
dispatchEvent(new WhiteboardDrawEvent(WhiteboardDrawEvent.CLEAR));
} else if (graphicType == WhiteboardConstants.TYPE_UNDO) {
sendUndoCommand();
} else {
canvas.setGraphicType(graphicType);
canvas.setTool(toolType);
if (panzoomBtn != null) {
panzoomBtn.setTool(graphicType, toolType);
}
if (scribbleBtn != null) {
scribbleBtn.setTool(graphicType, toolType);
}
if (rectangleBtn != null) {
rectangleBtn.setTool(graphicType, toolType);
}
if (circleBtn != null) {
circleBtn.setTool(graphicType, toolType);
}
if (triangleBtn != null) {
triangleBtn.setTool(graphicType, toolType);
}
if (lineBtn != null) {
lineBtn.setTool(graphicType, toolType);
}
if (textBtn != null) {
textBtn.setTool(graphicType, toolType);
}
}
}
protected function changeColor(e:Event):void {
canvas.changeColor(e);
}
protected function changeFillColor(e:Event):void {
canvas.changeFillColor(e);
}
protected function changeThickness(e:Event):void {
canvas.changeThickness(e);
}
protected function toggleFill():void {
canvas.toggleFill();
}
protected function toggleTransparency():void {
canvas.toggleTransparency();
}
private function presenterMode(e:MadePresenterEvent):void {
if (canvas == null) return;
canvas.makeTextObjectsEditable(e);
setToolType(WhiteboardConstants.TYPE_ZOOM, null);
}
private function viewerMode(e:MadePresenterEvent):void {
canvas.makeTextObjectsUneditable(e);
if (!toolbarAllowed()) {
checkVisibility();
if (panzoomBtn) {
panzoomBtn.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
}
}
}
private function undoShortcut(e:ShortcutEvent):void{
trace(LOG + "Ctrl-Z got into undoShortcut");
sendUndoCommand();
}
private function sendUndoCommand():void {
// if (!canvas.isPageEmpty()) {
dispatchEvent(new WhiteboardDrawEvent(WhiteboardDrawEvent.UNDO));
// }
}
public function positionToolbar(window:PresentationWindow):void {
trace(LOG + "Positioning whiteboard toolbar");
presentationWindow = window;
presentationWindow.addEventListener(MoveEvent.MOVE, setPositionAndDepth);
presentationWindow.addEventListener(ResizeEvent.RESIZE, setPositionAndDepth);
presentationWindow.addEventListener(MouseEvent.CLICK, setPositionAndDepth);
if (!wbOptions.keepToolbarVisible) {
window.presCtrlBar.addEventListener(MouseEvent.ROLL_OVER, handleMouseOut);
window.presCtrlBar.addEventListener(MouseEvent.ROLL_OUT, handleMouseIn);
window.addEventListener(MouseEvent.ROLL_OVER, handleMouseIn);
window.addEventListener(MouseEvent.ROLL_OUT, handleMouseOut);
this.addEventListener(MouseEvent.ROLL_OVER, handleMouseIn);
this.addEventListener(MouseEvent.ROLL_OUT, handleMouseOut);
} else {
var listener1:Listener = new Listener();
listener1.method = checkVisibility;
listener1.type = MadePresenterEvent.SWITCH_TO_PRESENTER_MODE;
var listener2:Listener = new Listener();
listener2.method = checkVisibility;
listener2.type = MadePresenterEvent.SWITCH_TO_VIEWER_MODE;
//Do an initial check to see if the toolbar should be visible
checkVisibility();
}
}
private function refreshRole(e:ChangeMyRole):void {
checkVisibility();
}
private function checkVisibility(e:MadePresenterEvent = null):void {
if (toolbarAllowed() && slideLoaded && (wbOptions.keepToolbarVisible || mousedOver) && !presentationWindow.minimized) {
setPositionAndDepth();
showWhiteboardToolbar = true;
} else {
showWhiteboardToolbar = false;
}
}
private function setPositionAndDepth(e:Event = null):void {
this.x = presentationWindow.x + presentationWindow.width - 43;
this.y = presentationWindow.y + 30;
parent.setChildIndex(this, parent.numChildren - 1);
}
private function closeToolbar(e:StopWhiteboardModuleEvent):void {
parent.removeChild(this);
}
private function handleMouseIn(e:MouseEvent):void {
mousedOver = true;
checkVisibility();
}
private function handleMouseOut(e:MouseEvent = null):void {
mousedOver = false;
checkVisibility();
}
private function handleSlideLoaded(e:DisplaySlideEvent):void {
slideLoaded = true;
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) {
panzoomBtn.dispatchEvent(new MouseEvent(MouseEvent.CLICK));
}
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 {
if (wbOptions) {
if (wbOptions.whiteboardAccess == "presenter")
return isPresenter;
else if (wbOptions.whiteboardAccess == "moderator")
return isModerator || isPresenter;
else if (wbOptions.whiteboardAccess == "all")
return true;
else
return false;
} else
return false;
}
/** Helper method to test whether this user is the presenter */
private function get isPresenter():Boolean {
return UsersUtil.amIPresenter();
}
private function get isModerator():Boolean {
return UsersUtil.amIModerator();
}
]]>
</mx:Script>
<!-- Now, every 'tool' has two types of identifiers, one is found in WhiteboardConstants
that identifies the "category" of the tool (ex. shape vs text), and the other specifies the
tool itself (ex. line tool vs triangle tool, even though both are "shapes")
-->
<wbBtns:PanZoomButton id="panzoomBtn"
tabIndex="{baseIndex}"
visible="{showWhiteboardToolbar}"/>
<mx:Spacer height="10" visible="{showWhiteboardToolbar}"/>
<wbBtns:ScribbleButton id="scribbleBtn"
tabIndex="{baseIndex+1}"
visible="{showWhiteboardToolbar}"/>
<wbBtns:RectangleButton id="rectangleBtn"
tabIndex="{baseIndex+2}"
visible="{showWhiteboardToolbar}"/>
<wbBtns:CircleButton id="circleBtn"
tabIndex="{baseIndex+3}"
visible="{showWhiteboardToolbar}"/>
<wbBtns:TriangleButton id="triangleBtn"
tabIndex="{baseIndex+4}"
visible="{showWhiteboardToolbar}"/>
<wbBtns:LineButton id="lineBtn"
tabIndex="{baseIndex+5}"
visible="{showWhiteboardToolbar}"/>
<wbBtns:TextButton id="textBtn"
tabIndex="{baseIndex+6}"
visible="{showWhiteboardToolbar}"/>
<mx:Spacer height="5" visible="{showWhiteboardToolbar}"/>
<wbBtns:ClearButton id="clearBtn"
tabIndex="{baseIndex+7}"
visible="{showWhiteboardToolbar}"/>
<wbBtns:UndoButton id="undoBtn"
tabIndex="{baseIndex+8}"
visible="{showWhiteboardToolbar}"/>
<mx:Spacer height="5" visible="{showWhiteboardToolbar}"/>
<!--
Properties that were removed from original color picker:
swatchPanelStyleName="colorPickerStyle"
dataProvider="{colorPickerColours}"
-->
<!-- Layout is really bad right now, and is confusing. Basically, there are two
of ColorPickers, one for the "line" color for the outlines of shapes, and the other for
the "fill" color that is used only if "fill" is enabled in WhiteboardCanvasModel
-->
<mx:ColorPicker change="changeColor(event)" id="cpik" visible="{showWhiteboardToolbar}"
selectedColor="0x000000" width="30" dataProvider="{colorPickerColours}" swatchPanelStyleName="colorPickerStyle"
toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.color')}"
tabIndex="{baseIndex+9}"
accessibilityName="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.color')}"/>
<mx:Spacer height="3" visible="{showWhiteboardToolbar}"/>
<mx:Image source="{thick_icon}" horizontalAlign="center" width="30" visible="{showWhiteboardToolbar}"/>
<mx:VSlider height="50" id="sld" change="changeThickness(event)" visible="{showWhiteboardToolbar}"
toolTip="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.thickness.accessibilityName')}"
minimum="1" maximum="30"
useHandCursor="true" value="2" showDataTip="true" snapInterval="1" dataTipOffset="0" labelOffset="0"
tabIndex="{baseIndex+10}"
accessibilityName="{ResourceUtil.getInstance().getString('bbb.highlighter.toolbar.thickness.accessibilityName')}" />
<mx:Image source="{thin_icon}" horizontalAlign="center" width="30" visible="{showWhiteboardToolbar}"/>
</mx:VBox>

View File

@ -48,6 +48,7 @@ import org.bigbluebutton.api.messaging.messages.RegisterUser;
import org.bigbluebutton.api.messaging.messages.RemoveExpiredMeetings;
import org.bigbluebutton.api.messaging.messages.UserJoined;
import org.bigbluebutton.api.messaging.messages.UserLeft;
import org.bigbluebutton.api.messaging.messages.UserRoleChanged;
import org.bigbluebutton.api.messaging.messages.UserStatusChanged;
import org.bigbluebutton.web.services.ExpiredMeetingCleanupTimerTask;
import org.bigbluebutton.web.services.KeepAliveService;
@ -614,6 +615,21 @@ public class MeetingService implements MessageListener {
}
log.warn("The meeting " + message.meetingId + " doesn't exist");
}
private void userRoleChanged(UserRoleChanged message) {
Meeting m = getMeeting(message.meetingId);
if (m != null) {
User user = m.getUserById(message.userId);
if(user != null){
user.setRole(message.role);
log.debug("Setting new role in meeting " + message.meetingId + " for participant:" + user.getFullname());
return;
}
log.warn("The participant " + message.userId + " doesn't exist in the meeting " + message.meetingId);
return;
}
log.warn("The meeting " + message.meetingId + " doesn't exist");
}
private void processMessage(final IMessage message) {
Runnable task = new Runnable() {
@ -633,6 +649,8 @@ public class MeetingService implements MessageListener {
userLeft((UserLeft)message);
} else if (message instanceof UserStatusChanged) {
updatedStatus((UserStatusChanged)message);
} else if (message instanceof UserRoleChanged) {
userRoleChanged((UserRoleChanged)message);
} else if (message instanceof RemoveExpiredMeetings) {
checkAndRemoveExpiredMeetings();
} else if (message instanceof CreateMeeting) {

View File

@ -10,6 +10,7 @@ import org.bigbluebutton.api.messaging.messages.MeetingEnded;
import org.bigbluebutton.api.messaging.messages.MeetingStarted;
import org.bigbluebutton.api.messaging.messages.UserJoined;
import org.bigbluebutton.api.messaging.messages.UserLeft;
import org.bigbluebutton.api.messaging.messages.UserRoleChanged;
import org.bigbluebutton.api.messaging.messages.UserStatusChanged;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -122,6 +123,14 @@ public class MeetingMessageHandler implements MessageHandler {
for (MessageListener listener : listeners) {
listener.handle(new UserLeft(meetingId, userid));
}
} else if(MessagingConstants.USER_ROLE_CHANGE_EVENT.equalsIgnoreCase(messageName)) {
System.out.println("Handling [" + messageName + "] message.");
String meetingId = payload.get("meeting_id").getAsString();
String userid = payload.get("userid").getAsString();
String role = payload.get("role").getAsString();
for (MessageListener listener : listeners) {
listener.handle(new UserRoleChanged(meetingId, userid, role));
}
}
}
}

View File

@ -47,6 +47,7 @@ public class MessagingConstants {
public static final String USER_JOINED_EVENT = "user_joined_message";
public static final String USER_LEFT_EVENT = "user_left_message";
public static final String USER_STATUS_CHANGE_EVENT = "user_status_changed_message";
public static final String USER_ROLE_CHANGE_EVENT = "user_role_changed_message";
public static final String SEND_POLLS_EVENT = "SendPollsEvent";

View File

@ -0,0 +1,13 @@
package org.bigbluebutton.api.messaging.messages;
public class UserRoleChanged implements IMessage {
public final String meetingId;
public final String userId;
public final String role;
public UserRoleChanged(String meetingId, String userId, String role) {
this.meetingId = meetingId;
this.userId = userId;
this.role = role;
}
}