diff --git a/resources/images/images.properties b/resources/images/images.properties index 6415c7f57..e91b46862 100644 --- a/resources/images/images.properties +++ b/resources/images/images.properties @@ -77,6 +77,16 @@ service.gui.icons.LEAVE_ICON=resources/images/impl/gui/common/leave.png service.gui.icons.HOLD_STATUS_ICON=resources/images/impl/gui/common/holdStatusIcon.png service.gui.icons.MUTE_STATUS_ICON=resources/images/impl/gui/common/muteStatusIcon.png service.gui.icons.DEFAULT_FILE_ICON=resources/images/impl/gui/common/defaultFileIcon.png +service.gui.icons.CHATROOM_MEMBER_OWNER=resources/images/impl/gui/common/owner.png +service.gui.icons.CHATROOM_MEMBER_ADMIN=resources/images/impl/gui/common/admin.png +service.gui.icons.CHATROOM_MEMBER_MODERATOR=resources/images/impl/gui/common/moderator.png +service.gui.icons.CHATROOM_MEMBER_STANDARD=resources/images/impl/gui/common/standard.png +service.gui.icons.CHATROOM_MEMBER_GUEST=resources/images/impl/gui/common/guest.png +service.gui.icons.CHATROOM_MEMBER_SILENT=resources/images/impl/gui/common/silent.png +service.gui.icons.CHANGE_ROOM_SUBJECT_16x16=resources/images/impl/gui/common/changeSubject16x16.png +service.gui.icons.CHANGE_NICKNAME_16x16=resources/images/impl/gui/common/changeNickname16x16.png +service.gui.icons.BAN_16x16=resources/images/impl/gui/common/ban16x16.png +service.gui.icons.KICK_16x16=resources/images/impl/gui/common/kick16x16.png # Status icons service.gui.statusicons.USER_ONLINE_ICON=resources/images/impl/gui/common/statusicons/online.png @@ -152,6 +162,7 @@ service.gui.buttons.MORE_ACTIONS_ROLLOVER_BUTTON=resources/images/impl/gui/butto service.gui.buttons.HIDE_ACTIONS_BUTTON=resources/images/impl/gui/buttons/hideMoreActions.png service.gui.buttons.HIDE_ACTIONS_ROLLOVER_BUTTON=resources/images/impl/gui/buttons/hideMoreActionsRollover.png service.gui.buttons.CALL_PEER_TOOLS=resources/images/impl/gui/buttons/tools.png +service.gui.buttons.CHAT_ROOM_CONFIG=resources/images/impl/gui/buttons/chatRoomConfig.png # Sound level icons service.gui.soundlevel.SOUND_LEVEL_ACTIVE=resources/images/impl/gui/common/soundlevel/soundActive.png diff --git a/resources/images/impl/gui/buttons/chatRoomConfig.png b/resources/images/impl/gui/buttons/chatRoomConfig.png new file mode 100644 index 000000000..d9e420813 Binary files /dev/null and b/resources/images/impl/gui/buttons/chatRoomConfig.png differ diff --git a/resources/images/impl/gui/common/README b/resources/images/impl/gui/common/README new file mode 100644 index 000000000..916fcc09f --- /dev/null +++ b/resources/images/impl/gui/common/README @@ -0,0 +1,2 @@ +Location for PNGs in SIP Communicator's trunk: +/resources/images/impl/gui/common/ diff --git a/resources/images/impl/gui/common/admin.png b/resources/images/impl/gui/common/admin.png new file mode 100644 index 000000000..09ef1808f Binary files /dev/null and b/resources/images/impl/gui/common/admin.png differ diff --git a/resources/images/impl/gui/common/ban16x16.png b/resources/images/impl/gui/common/ban16x16.png new file mode 100644 index 000000000..7818b17e5 Binary files /dev/null and b/resources/images/impl/gui/common/ban16x16.png differ diff --git a/resources/images/impl/gui/common/changeNickname16x16.png b/resources/images/impl/gui/common/changeNickname16x16.png new file mode 100644 index 000000000..4a1befe42 Binary files /dev/null and b/resources/images/impl/gui/common/changeNickname16x16.png differ diff --git a/resources/images/impl/gui/common/changeSubject16x16.png b/resources/images/impl/gui/common/changeSubject16x16.png new file mode 100644 index 000000000..eafc56578 Binary files /dev/null and b/resources/images/impl/gui/common/changeSubject16x16.png differ diff --git a/resources/images/impl/gui/common/guest.png b/resources/images/impl/gui/common/guest.png new file mode 100644 index 000000000..791e80c66 Binary files /dev/null and b/resources/images/impl/gui/common/guest.png differ diff --git a/resources/images/impl/gui/common/kick16x16.png b/resources/images/impl/gui/common/kick16x16.png new file mode 100644 index 000000000..0fa13242f Binary files /dev/null and b/resources/images/impl/gui/common/kick16x16.png differ diff --git a/resources/images/impl/gui/common/moderator.png b/resources/images/impl/gui/common/moderator.png new file mode 100644 index 000000000..d36008cef Binary files /dev/null and b/resources/images/impl/gui/common/moderator.png differ diff --git a/resources/images/impl/gui/common/owner.png b/resources/images/impl/gui/common/owner.png new file mode 100644 index 000000000..2e7d0c3dc Binary files /dev/null and b/resources/images/impl/gui/common/owner.png differ diff --git a/resources/images/impl/gui/common/silent.png b/resources/images/impl/gui/common/silent.png new file mode 100644 index 000000000..b1ddbbfc6 Binary files /dev/null and b/resources/images/impl/gui/common/silent.png differ diff --git a/resources/images/impl/gui/common/standard.png b/resources/images/impl/gui/common/standard.png new file mode 100644 index 000000000..5135bac31 Binary files /dev/null and b/resources/images/impl/gui/common/standard.png differ diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 6889df9a2..c4260b214 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -53,11 +53,13 @@ service.gui.ADD_GROUP_NET_ERROR=Failed to add group with name: {0}. The problem service.gui.ADD_GROUP_ERROR=Failed to add group with name: {0}. service.gui.ADD_GROUP=Create group service.gui.ADD_SUBCONTACT=&Add subcontact +service.gui.ADMINISTRATOR=administrator service.gui.ADVANCED=&Advanced service.gui.ALL=&All service.gui.ALL_CONTACTS=&All contacts service.gui.APPLY=&Apply service.gui.ARE_CALLING=are calling... +service.gui.ARE_NOW=You are now {0} service.gui.AT=at service.gui.AUTHORIZATION_ACCEPTED=contact has accepted your authorization request. service.gui.AUTHENTICATION_FAILED=Authentication failed. The password you entered is not valid. @@ -79,6 +81,10 @@ service.gui.BUSY_MESSAGE=Sorry, I'm busy right now. service.gui.CALL=Call service.gui.CALL_VIA=Call via: service.gui.CANCEL=&Cancel +service.gui.CHANGE_ROOM_SUBJECT=Change room's subject... +service.gui.CHANGE_ROOM_SUBJECT_LABEL=In he field below, you can enter the new subject for this room. +service.gui.CHANGE_NICKNAME=Change nickname... +service.gui.CHANGE_NICKNAME_LABEL=In he field below, you can enter your new nickname. service.gui.CHAT_ROOM_ALREADY_JOINED=The {0} chat room is already joined. service.gui.CHAT_ROOM_CONFIGURATION={0} chat room configuration service.gui.CHAT_ROOM_CONFIGURATION_FAILED=Failed to obtain the {0} chat room configuration form. @@ -118,7 +124,7 @@ service.gui.COPY=&Copy service.gui.COPY_LINK=Copy &link service.gui.CREATE=C&reate service.gui.CREATE_CHAT_ROOM=&Create chat room... -service.gui.CREATE_CHAT_ROOM_ERROR=Failed to create chat room with name: {0}. +service.gui.CREATE_CHAT_ROOM_ERROR=Failed to create {0} chat room. service.gui.CREATE_CHAT_ROOM_WIZARD=Create chat room wizard service.gui.CREATE_CONFERENCE_CALL=&Create a conference call... service.gui.CREATE_CONFERENCE_CHAT=&Create a conference chat... @@ -182,6 +188,12 @@ service.gui.FONT_ITALIC=Italic service.gui.FONT_SIZE=Size service.gui.FONT_STYLE=Style service.gui.FONT_UNDERLINE=Underline +service.gui.GRANT_OWNERSHIP=Grant ownership... +service.gui.GRANT_ADMIN=Grant administrator... +service.gui.GRANT_MODERATOR=Grant moderator +service.gui.GRANT_MEMBERSHIP=Grant membership +service.gui.GRANT_VOICE=Grant voice +service.gui.GUEST=visitor service.gui.HANG_UP=Hang up service.gui.HELP=&Help service.gui.HIDE_OFFLINE_CONTACTS=Hide inactive contacts @@ -202,6 +214,7 @@ service.gui.INVITE_CONTACT_TO_CHAT=Invite contacts to chat service.gui.INVITE_CONTACT_TO_CALL=Invite contacts to call service.gui.INVITE_REASON=Invite reason service.gui.IS_CALLING=is calling... +service.gui.IS_NOW={0} is now {1} service.gui.JOIN=&Join service.gui.JOIN_AS=J&oin as service.gui.CLOSE_CHAT_ROOM_DIALOG=C&lose @@ -225,6 +238,8 @@ service.gui.LOGIN_INVALID_PROPERTIES_ERROR=Unable to log in with account: User n service.gui.LOGIN_WINDOW_TITLE=Login {0} service.gui.LOGOFF_NOT_SUCCEEDED=An error occured while logging off with the following account: User name: {0}, Server name: {1}. service.gui.ME=me +service.gui.MEMBER=member +service.gui.MODERATOR=moderator service.gui.MORE=See more service.gui.MOVE=Move service.gui.MOVE_SUBCONTACT=M&ove contact @@ -273,6 +288,7 @@ service.gui.OPEN_TOOLS=Open Tools Menu service.gui.OPTIONS=Options service.gui.OR=or service.gui.OR_ENTER_PHONE_NUMBER=Or enter phone number here... +service.gui.OWNER=owner of the room service.gui.PASSWORD=Password service.gui.PASTE=&Paste service.gui.PREVIOUS=Previous @@ -304,6 +320,11 @@ service.gui.REQUEST=&Request service.gui.REQUEST_AUTHORIZATION=&Request authorization service.gui.REQUEST_AUTHORIZATION_MSG=Can''t add {0} to your Contact List. {0} must authorize your request to add him/her. Please enter your request below. service.gui.RETRY=Retry +service.gui.REVOKE_OWNERSHIP=Revoke ownership +service.gui.REVOKE_ADMIN=Revoke admin +service.gui.REVOKE_MODERATOR=Revoke moderator +service.gui.REVOKE_MEMBERSHIP=Revoke membership +service.gui.REVOKE_VOICE=Revoke voice service.gui.ROOT_GROUP=Root group service.gui.SAVE=&Save service.gui.SEARCH=&Search @@ -383,6 +404,7 @@ service.gui.SECURITY_INFO=Security information service.gui.SECURITY_WARNING=Security warning service.gui.SECURITY_ERROR=Security error service.gui.SPEED=Speed: +service.gui.SILENT_MEMBER=silent member service.gui.JANUARY=Jan service.gui.FEBRUARY=Feb diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatContactRightButtonMenu.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatContactRightButtonMenu.java index 747ce5268..07d358bcb 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatContactRightButtonMenu.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatContactRightButtonMenu.java @@ -17,7 +17,6 @@ import net.java.sip.communicator.impl.gui.utils.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.*; -import net.java.sip.communicator.util.swing.*; /** * The ChatContactRightButtonMenu is the menu, opened when user clicks @@ -31,31 +30,83 @@ public class ChatContactRightButtonMenu implements ActionListener { private Logger logger = Logger.getLogger(ChatContactRightButtonMenu.class); - - private JMenuItem kickItem = new JMenuItem( - GuiActivator.getResources().getI18NString("service.gui.KICK")); - - private JMenuItem banItem = new JMenuItem( - GuiActivator.getResources().getI18NString("service.gui.BAN")); - - private static String KICK_OPERATION = "Kick"; - - private static String BAN_OPERATION = "Ban"; - - private ChatPanel chatPanel; - - private ChatContact chatContact; + + private final JMenuItem kickItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.KICK")); + private final JMenuItem banItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.BAN")); + + private final JMenuItem changeRoomSubjectItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.CHANGE_ROOM_SUBJECT")); + private final JMenuItem changeNicknameItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.CHANGE_NICKNAME")); + + private final JMenuItem grantOwnershipItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.GRANT_OWNERSHIP")); + private final JMenuItem grantAdminItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.GRANT_ADMIN")); + private final JMenuItem grantMembershipItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.GRANT_MEMBERSHIP")); + private final JMenuItem grantModeratorItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.GRANT_MODERATOR")); + private final JMenuItem grantVoiceItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.GRANT_VOICE")); + + private final JMenuItem revokeOwnershipItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.REVOKE_OWNERSHIP")); + private final JMenuItem revokeAdminItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.REVOKE_ADMIN")); + private final JMenuItem revokeMembershipItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.REVOKE_MEMBERSHIP")); + private final JMenuItem revokeModeratorItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.REVOKE_MODERATOR")); + private final JMenuItem revokeVoiceItem + = new JMenuItem(GuiActivator.getResources().getI18NString( + "service.gui.REVOKE_VOICE")); + + private final ChatPanel chatPanel; + + /** + * The contact associated with this menu + */ + private final ChatContact chatContact; + + /** + * The Chatroom in which the chatContact is currently participating. + */ + private ChatRoom room; /** * Creates an instance of ChatRoomsListRightButtonMenu. + * @param chatPanel the chat panel containing this menu + * @param chatContact the contact */ - public ChatContactRightButtonMenu(ChatPanel chatPanel, - ChatContact chatContact) + public ChatContactRightButtonMenu( ChatPanel chatPanel, + ChatContact chatContact) { this.chatPanel = chatPanel; - + this.chatContact = chatContact; - + + Object descriptor + = chatPanel.getChatSession().getDescriptor(); + + if (descriptor instanceof ChatRoomWrapper) + this.room = ((ChatRoomWrapper) descriptor).getChatRoom(); + this.setLocation(getLocation()); this.init(); @@ -66,20 +117,182 @@ public ChatContactRightButtonMenu(ChatPanel chatPanel, */ private void init() { - this.add(kickItem); - this.add(banItem); - - this.kickItem.setName("kick"); - this.banItem.setName("ban"); - this.kickItem.setMnemonic( GuiActivator.getResources().getI18nMnemonic("service.gui.KICK")); this.banItem.setMnemonic( GuiActivator.getResources().getI18nMnemonic("service.gui.BAN")); + this.grantAdminItem.setMnemonic( + GuiActivator.getResources().getI18nMnemonic( + "service.gui.GRANT_ADMIN")); + this.grantMembershipItem.setMnemonic( + GuiActivator.getResources().getI18nMnemonic( + "service.gui.GRANT_MEMBERSHIP")); + this.grantModeratorItem.setMnemonic( + GuiActivator.getResources().getI18nMnemonic( + "service.gui.GRANT_MODERATOR")); + this.grantOwnershipItem.setMnemonic( + GuiActivator.getResources().getI18nMnemonic( + "service.gui.GRANT_OWNERSHIP")); + this.grantVoiceItem.setMnemonic( + GuiActivator.getResources().getI18nMnemonic( + "service.gui.GRANT_VOICE")); + this.revokeAdminItem.setMnemonic( + GuiActivator.getResources().getI18nMnemonic( + "service.gui.REVOKE_ADMIN")); + this.revokeMembershipItem.setMnemonic( + GuiActivator.getResources().getI18nMnemonic( + "service.gui.REVOKE_MEMBERSHIP")); + this.revokeModeratorItem.setMnemonic( + GuiActivator.getResources().getI18nMnemonic( + "service.gui.REVOKE_MODERATOR")); + this.revokeOwnershipItem.setMnemonic( + GuiActivator.getResources().getI18nMnemonic( + "service.gui.REVOKE_OWNERSHIP")); + this.revokeVoiceItem.setMnemonic( + GuiActivator.getResources().getI18nMnemonic( + "service.gui.REVOKE_VOICE")); + this.changeNicknameItem.setMnemonic( + GuiActivator.getResources().getI18nMnemonic( + "service.gui.CHANGE_NICKNAME")); + this.changeNicknameItem.setMnemonic( + GuiActivator.getResources().getI18nMnemonic( + "service.gui.CHANGE_ROOM_SUBJECT")); + this.kickItem.addActionListener(this); this.banItem.addActionListener(this); + this.changeNicknameItem.addActionListener(this); + this.changeRoomSubjectItem.addActionListener(this); + this.grantAdminItem.addActionListener(this); + this.grantMembershipItem.addActionListener(this); + this.grantModeratorItem.addActionListener(this); + this.grantOwnershipItem.addActionListener(this); + this.grantVoiceItem.addActionListener(this); + this.revokeAdminItem.addActionListener(this); + this.revokeMembershipItem.addActionListener(this); + this.revokeModeratorItem.addActionListener(this); + this.revokeOwnershipItem.addActionListener(this); + this.revokeVoiceItem.addActionListener(this); + + this.grantOwnershipItem.setIcon(ImageUtils.getScaledRoundedIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_OWNER), 16, 16)); + this.grantAdminItem.setIcon(ImageUtils.getScaledRoundedIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_ADMIN), 16, 16)); + this.grantMembershipItem.setIcon(ImageUtils.getScaledRoundedIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_STANDARD), 16, 16)); + this.grantModeratorItem.setIcon(ImageUtils.getScaledRoundedIcon( + ImageLoader.getImage( + ImageLoader.CHATROOM_MEMBER_MODERATOR), 16, 16)); + this.grantVoiceItem.setIcon(ImageUtils.getScaledRoundedIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_STANDARD), 16, 16)); + this.revokeAdminItem.setIcon(ImageUtils.getScaledRoundedIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_STANDARD), 16, 16)); + this.revokeMembershipItem.setIcon(ImageUtils.getScaledRoundedIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_GUEST), 16, 16)); + this.revokeModeratorItem.setIcon(ImageUtils.getScaledRoundedIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_STANDARD), 16, 16)); + this.revokeOwnershipItem.setIcon(ImageUtils.getScaledRoundedIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_ADMIN), 16, 16)); + this.revokeVoiceItem.setIcon(ImageUtils.getScaledRoundedIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_SILENT), 16, 16)); + this.kickItem.setIcon(new ImageIcon(ImageLoader.getImage( + ImageLoader.KICK_ICON_16x16))); + this.banItem.setIcon(new ImageIcon(ImageLoader.getImage( + ImageLoader.BAN_ICON_16x16))); + this.changeNicknameItem.setIcon(new ImageIcon(ImageLoader.getImage( + ImageLoader.CHANGE_NICKNAME_ICON_16x16))); + this.changeRoomSubjectItem.setIcon(new ImageIcon(ImageLoader.getImage( + ImageLoader.CHANGE_ROOM_SUBJECT_ICON_16x16))); + int roleIndex = ((ChatRoomMember) + chatContact.getDescriptor()).getRole().getRoleIndex(); + String roleName = ((ChatRoomMember) + chatContact.getDescriptor()).getRole().getRoleName(); + + if(chatContact.getName().equals(room.getUserNickname())) + { + roleName = room.getUserRole().getRoleName(); + roleIndex = room.getUserRole().getRoleIndex(); + } + + JLabel jl_username + = new JLabel(" "+chatContact.getName()+" ("+roleName+") "); + jl_username.setFont(jl_username.getFont().deriveFont(Font.BOLD)); + + this.add(jl_username); + this.addSeparator(); + + OperationSetPersistentPresence opSet + = (OperationSetPersistentPresence) room.getParentProvider() + .getOperationSet(OperationSetPersistentPresence.class); + + Contact c = opSet.findContactByID(room.getUserNickname()); + + // Here we build the menu when the local user cell renderer is clicked: + if(chatContact.getName().equals(room.getUserNickname())) + { + if(roleIndex >= 50) + { + // It means we are at least a moderator, so we can change room's + // subject: + this.add(this.changeRoomSubjectItem); + } + + this.add(this.changeNicknameItem); + } + else + { + if(room.getUserRole().getRoleIndex() >= 50) + { + if(roleIndex <= 40) + { + this.add(this.kickItem); + + // Admins and owners can ban members: + if(room.getUserRole().getRoleIndex() >= 60 && roleIndex < 50) + { + this.add(this.banItem); + } + this.addSeparator(); + } + + // we must at least be a moderator for managing voice rights + if(roleIndex <= 20) + this.add(this.grantVoiceItem); + else if(roleIndex == 40 || roleIndex == 30) + this.add(this.revokeVoiceItem); + } + + if(room.getUserRole().getRoleIndex() >= 60) + { + // we must at least be an admin to manage membership + if(roleIndex < 40) + this.add(this.grantMembershipItem); + else if(roleIndex == 40) + this.add(this.revokeMembershipItem); + + if(roleIndex < 50) // room admins can edit moderators list + this.add(this.grantModeratorItem); + else if(roleIndex == 50) + this.add(this.revokeModeratorItem); + } + + // only room owners can edit admins list + if(room.getUserRole().getRoleIndex() == 70) + { + if(roleIndex != 60 && roleIndex >= 30) + // room owners can grant members or unaffiliated users as admins + this.add(this.grantAdminItem); + else if(roleIndex == 60) + this.add(this.revokeAdminItem); + + // room owners can edit owners list + if(roleIndex != 70 && roleIndex >= 40) + this.add(this.grantOwnershipItem); + else if(roleIndex == 70) + this.add(this.revokeOwnershipItem); + } + } } /** @@ -89,130 +302,143 @@ private void init() public void actionPerformed(ActionEvent e) { JMenuItem menuItem = (JMenuItem) e.getSource(); - String itemName = menuItem.getName(); - if (itemName.equals("kick")) + if (menuItem.equals(kickItem)) { - new ReasonDialog(KICK_OPERATION).setVisible(true); + ChatOperationReasonDialog reasonDialog + = new ChatOperationReasonDialog(); + + int result = new ChatOperationReasonDialog().showDialog(); + + if (result == 0) + new KickParticipantThread( room, + reasonDialog.getReason()).start(); } - else if (itemName.equals("ban")) + else if (menuItem.equals(banItem)) { - new ReasonDialog(BAN_OPERATION).setVisible(true); + ChatOperationReasonDialog reasonDialog + = new ChatOperationReasonDialog(); + + int result = new ChatOperationReasonDialog().showDialog(); + + if (result == 0) + new BanParticipantThread( room, + reasonDialog.getReason()).start(); } - } - - private class ReasonDialog extends SIPCommDialog - { - private JLabel iconLabel = new JLabel(new ImageIcon( - ImageLoader.getImage(ImageLoader.REASON_DIALOG_ICON))); - - private JLabel infoLabel = new JLabel( - GuiActivator.getResources() - .getI18NString("service.gui.SPECIFY_REASON")); - - private JLabel reasonLabel = new JLabel( - GuiActivator.getResources() - .getI18NString("service.gui.REASON") + ":"); - - private JTextField reasonField = new JTextField(); - - private JButton okButton = new JButton( - GuiActivator.getResources().getI18NString("service.gui.OK")); - - private JButton cancelButton = new JButton( - GuiActivator.getResources().getI18NString("service.gui.CANCEL")); - - private JPanel buttonsPanel - = new JPanel(new FlowLayout(FlowLayout.RIGHT)); - - private JPanel titlePanel = new JPanel(new BorderLayout(10, 10)); - - private JPanel mainPanel = new JPanel(new BorderLayout(10, 10)); - - private String operationType; - - ReasonDialog(String operation) + else if (menuItem.equals(changeRoomSubjectItem)) { - super(chatPanel.getChatWindow()); - - this.setTitle( - GuiActivator.getResources().getI18NString("service.gui.REASON")); - - this.operationType = operation; - - this.buttonsPanel.add(okButton); - this.buttonsPanel.add(cancelButton); - - okButton.addActionListener(new ActionListener() + ChatOperationReasonDialog reasonDialog + = new ChatOperationReasonDialog( + GuiActivator.getResources().getI18NString( + "service.gui.CHANGE_ROOM_SUBJECT"), + GuiActivator.getResources().getI18NString( + "service.gui.CHANGE_ROOM_SUBJECT_LABEL")); + + int result = new ChatOperationReasonDialog().showDialog(); + + if (result == 0) { - public void actionPerformed(ActionEvent e) + try { - //This menu is shown only for chat rooms, so we're sure - // here that we deal with a multi user chat. - ChatRoomWrapper chatRoomWrapper - = (ChatRoomWrapper) chatPanel - .getChatSession().getDescriptor(); - - ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); + room.setSubject(reasonDialog.getReason().trim()); + } + catch (OperationFailedException ex) + { + ex.printStackTrace(); + } + } + } + else if (menuItem.equals(changeNicknameItem)) + { + ChatOperationReasonDialog reasonDialog + = new ChatOperationReasonDialog( + GuiActivator.getResources().getI18NString( + "service.gui.CHANGE_NICKNAME"), + GuiActivator.getResources().getI18NString( + "service.gui.CHANGE_NICKNAME_LABEL")); - if(chatRoom == null) - { - new ErrorDialog(chatPanel.getChatWindow(), - GuiActivator.getResources() - .getI18NString("service.gui.ERROR"), - GuiActivator.getResources() - .getI18NString("service.gui.CHAT_ROOM_NOT_JOINED")) - .setVisible(true); + int result = new ChatOperationReasonDialog().showDialog(); - return; - } - - if (operationType.equals(KICK_OPERATION)) - { - new KickParticipantThread(chatRoom, - reasonField.getText()).start(); - } - else if (operationType.equals(BAN_OPERATION)) - { - new BanParticipantThread(chatRoom, - reasonField.getText()).start(); - } - - ReasonDialog.this.setVisible(false); - } - }); - - cancelButton.addActionListener(new ActionListener() + if (result == 0) { - public void actionPerformed(ActionEvent e) + try + { + room.setUserNickname(reasonDialog.getReason().trim()); + } + catch (OperationFailedException ex) { - ReasonDialog.this.setVisible(false); + ex.printStackTrace(); } - }); - - this.infoLabel.setFont(infoLabel.getFont().deriveFont(Font.BOLD)); - - this.titlePanel.add(iconLabel, BorderLayout.WEST); - this.titlePanel.add(infoLabel, BorderLayout.CENTER); - - this.mainPanel.add(titlePanel, BorderLayout.NORTH); - this.mainPanel.add(reasonLabel, BorderLayout.WEST); - this.mainPanel.add(reasonField, BorderLayout.CENTER); - this.mainPanel.add(buttonsPanel, BorderLayout.SOUTH); - - this.mainPanel.setBorder( - BorderFactory.createEmptyBorder(10, 10, 10, 10)); - - this.getContentPane().add(mainPanel); - - this.pack(); + } } - - protected void close(boolean isEscaped) - { + else if (menuItem.equals(grantVoiceItem)) + { + room.grantVoice(chatContact.getName()); + ((ChatRoomMember)chatContact.getDescriptor()).setRole( + ChatRoomMemberRole.GUEST); + } + else if (menuItem.equals(grantMembershipItem)) + { + room.grantMembership(((ChatRoomMember) + chatContact.getDescriptor()).getContactAddress()); + ((ChatRoomMember)chatContact.getDescriptor()).setRole( + ChatRoomMemberRole.MEMBER); + } + else if(menuItem.equals(grantModeratorItem)) + { + room.grantModerator(chatContact.getName()); + ((ChatRoomMember)chatContact.getDescriptor()).setRole( + ChatRoomMemberRole.MODERATOR); + } + else if(menuItem.equals(grantAdminItem)) + { + room.grantAdmin(((ChatRoomMember) chatContact + .getDescriptor()).getContactAddress()); + ((ChatRoomMember)chatContact.getDescriptor()).setRole( + ChatRoomMemberRole.ADMINISTRATOR); + } + else if(menuItem.equals(grantOwnershipItem)) + { + room.grantOwnership(((ChatRoomMember) + chatContact.getDescriptor()).getContactAddress()); + ((ChatRoomMember)chatContact.getDescriptor()).setRole( + ChatRoomMemberRole.OWNER); + } + else if(menuItem.equals(revokeOwnershipItem)) + { + room.revokeOwnership(((ChatRoomMember) + chatContact.getDescriptor()).getContactAddress()); + ((ChatRoomMember)chatContact.getDescriptor()).setRole( + ChatRoomMemberRole.ADMINISTRATOR); + } + else if(menuItem.equals(revokeAdminItem)) + { + room.revokeAdmin(((ChatRoomMember) + chatContact.getDescriptor()).getContactAddress()); + ((ChatRoomMember)chatContact.getDescriptor()).setRole( + ChatRoomMemberRole.MEMBER); + } + else if(menuItem.equals(revokeModeratorItem)) + { + room.revokeModerator(chatContact.getName()); + ((ChatRoomMember)chatContact.getDescriptor()).setRole( + ChatRoomMemberRole.MEMBER); + } + else if(menuItem.equals(revokeMembershipItem)) + { + room.revokeMembership(((ChatRoomMember) + chatContact.getDescriptor()).getContactAddress()); + ((ChatRoomMember)chatContact.getDescriptor()).setRole( + ChatRoomMemberRole.GUEST); + } + else if(menuItem.equals(revokeVoiceItem)) + { + room.revokeVoice(chatContact.getName()); + ((ChatRoomMember)chatContact.getDescriptor()).setRole( + ChatRoomMemberRole.SILENT_MEMBER); } } - + /** * Kicks the the selected chat room participant or shows a message to the * user that he/she has not enough permissions to do a ban. @@ -220,15 +446,15 @@ protected void close(boolean isEscaped) private class KickParticipantThread extends Thread { private final ChatRoom chatRoom; - + private final String reason; - + KickParticipantThread(ChatRoom chatRoom, String reason) { this.chatRoom = chatRoom; this.reason = reason; } - + public void run() { try diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatOperationReasonDialog.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatOperationReasonDialog.java new file mode 100644 index 000000000..0fe05c01d --- /dev/null +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatOperationReasonDialog.java @@ -0,0 +1,88 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.gui.main.chat; + +import java.awt.*; + +import javax.swing.*; + +import net.java.sip.communicator.impl.gui.*; +import net.java.sip.communicator.impl.gui.customcontrols.*; + +/** + * @author Yana Stamcheva + * @author Valentin Martinet + */ +public class ChatOperationReasonDialog extends MessageDialog +{ + private final JLabel reasonLabel = new JLabel( + GuiActivator.getResources() + .getI18NString("service.gui.REASON") + ":"); + + private final JTextField reasonField = new JTextField(); + + /** + * Creates an instance of ChatOperationReasonDialog using the + * default title and message. + */ + public ChatOperationReasonDialog() + { + this(null, + GuiActivator.getResources().getI18NString( + "service.gui.REASON"), + GuiActivator.getResources().getI18NString( + "service.gui.SPECIFY_REASON"), + GuiActivator.getResources().getI18NString( + "service.gui.OK")); + } + + /** + * Creates an instance of ChatOperationReasonDialog by specifying + * the title and the message shown in the dialog. + * @param title the title of this dialog + * @param message the message shown in this dialog + */ + public ChatOperationReasonDialog(String title, String message) + { + this(null, + title, + message, + GuiActivator.getResources().getI18NString( + "service.gui.OK")); + } + + /** + * Creates an instance of ChatOperationReasonDialog by specifying + * the parent window, the title and the message to show. + * @param chatWindow the parent window + * @param title the title of this dialog + * @param message the message shown in this dialog + * @param okButtonName the custom name of the ok button + */ + public ChatOperationReasonDialog( + ChatWindow chatWindow, String title, String message, String okButtonName) + { + super(chatWindow, title, message, okButtonName, false); + + JPanel reasonPanel = new JPanel(new BorderLayout()); + reasonPanel.add(reasonLabel, BorderLayout.WEST); + reasonPanel.add(reasonField, BorderLayout.CENTER); + + this.getContentPane().add(reasonPanel, BorderLayout.CENTER); + + this.pack(); + } + + /** + * Returns the text entered in the reason field. + * @return the text entered in the reason field + */ + public String getReason() + { + return reasonField.getText(); + } +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java index ab65a466b..c326ddb14 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java @@ -30,7 +30,6 @@ import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.util.*; import net.java.sip.communicator.util.swing.*; -import net.java.sip.communicator.util.swing.SwingWorker; // disambiguation /** * The ChatPanel is the panel, where users can write and send messages, @@ -49,6 +48,8 @@ public class ChatPanel implements ChatSessionRenderer, Chat, ChatConversationContainer, + ChatRoomMemberRoleListener, + ChatRoomLocalUserRoleListener, FileTransferStatusListener { private static final Logger logger = Logger.getLogger(ChatPanel.class); @@ -258,17 +259,20 @@ public void setChatSession(ChatSession chatSession) } else if (chatSession instanceof ConferenceChatSession) { + ConferenceChatSession confSession + = (ConferenceChatSession) chatSession; + removeChatTransportSelectorBox(); + confSession.addLocalUserRoleListener(this); + confSession.addMemberRoleListener(this); + + subjectPanel = new ChatRoomSubjectPanel(chatWindow, + (ConferenceChatSession) chatSession); -// We don't add the subject panel for now. It takes too much space -// and is not used. -// subjectPanel -// = new ChatRoomSubjectPanel( chatWindow, -// (ConferenceChatSession) chatSession); // The subject panel is added here, because it's specific for the // multi user chat and is not contained in the single chat chat panel. -// this.add(subjectPanel, BorderLayout.NORTH); + this.add(subjectPanel, BorderLayout.NORTH); } if (chatContactListPanel != null) @@ -384,6 +388,77 @@ public ChatSendPanel getChatSendPanel() return this.sendPanel; } + /** + * Returns the corresponding role description to the given role index. + * + * @param role to role index to analyse + * @return String the corresponding role description + */ + public String getRoleDescription(ChatRoomMemberRole role) + { + String roleDescription = null; + + switch(role) + { + case OWNER: roleDescription + = GuiActivator.getResources().getI18NString( + "service.gui.OWNER"); + break; + case ADMINISTRATOR: roleDescription + = GuiActivator.getResources().getI18NString( + "service.gui.ADMINISTRATOR"); + break; + case MODERATOR: roleDescription + = GuiActivator.getResources().getI18NString( + "service.gui.MODERATOR"); + break; + case MEMBER: roleDescription + = GuiActivator.getResources().getI18NString( + "service.gui.MEMBER"); + break; + case GUEST: roleDescription + = GuiActivator.getResources().getI18NString( + "service.gui.GUEST"); + break; + case SILENT_MEMBER: roleDescription + = GuiActivator.getResources().getI18NString( + "service.gui.SILENT_MEMBER"); + break; + default:; + } + + return roleDescription; + } + + /** + * Implements the memberRoleChanged() method. + * + * @param evt + */ + public void memberRoleChanged(ChatRoomMemberRoleChangeEvent evt) + { + this.conversationPanel.appendMessageToEnd( + "
" + + GuiActivator.getResources().getI18NString("service.gui.IS_NOW", + new String[]{evt.getSourceMember().getName(), + getRoleDescription(evt.getNewRole())}) + +"
"); + } + + /** + * Implements the localUserRoleChanged() method. + * + * @param evt + */ + public void localUserRoleChanged(ChatRoomLocalUserRoleChangeEvent evt) + { + this.conversationPanel.appendMessageToEnd( + "
" + +GuiActivator.getResources().getI18NString("service.gui.ARE_NOW", + new String[]{ + getRoleDescription(evt.getNewRole())}) +"
"); + } + /** * Every time the chat panel is shown we set it as a current chat panel. * This is done here and not in the Tab selection listener, because the tab @@ -1870,8 +1945,6 @@ public void inviteContacts( ChatTransport inviteChatTransport, if (chatSession instanceof MetaContactChatSession) { - String newChatName = inviteChatTransport.getDisplayName(); - chatContacts.add(inviteChatTransport.getName()); ConferenceChatManager conferenceChatManager @@ -1882,7 +1955,7 @@ public void inviteContacts( ChatTransport inviteChatTransport, getOperationSet(OperationSetMultiUserChat.class) != null) { ChatRoomWrapper chatRoomWrapper - = conferenceChatManager.createChatRoom(newChatName, + = conferenceChatManager.createChatRoom( inviteChatTransport.getProtocolProvider(), chatContacts); conferenceChatSession @@ -1892,7 +1965,7 @@ else if (inviteChatTransport.getProtocolProvider(). getOperationSet(OperationSetAdHocMultiUserChat.class) != null) { AdHocChatRoomWrapper chatRoomWrapper - = conferenceChatManager.createAdHocChatRoom(newChatName, + = conferenceChatManager.createAdHocChatRoom( inviteChatTransport.getProtocolProvider(), chatContacts); diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatContactCellRenderer.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatContactCellRenderer.java index 5815a6b73..1cb9dce2f 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatContactCellRenderer.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatContactCellRenderer.java @@ -8,18 +8,23 @@ package net.java.sip.communicator.impl.gui.main.chat.conference; import java.awt.*; +import java.util.*; import javax.swing.*; import net.java.sip.communicator.impl.gui.*; import net.java.sip.communicator.impl.gui.main.chat.*; import net.java.sip.communicator.impl.gui.main.contactlist.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.protocol.ServerStoredDetails.*; +import net.java.sip.communicator.util.*; /** - * The ChatContactCellRenderer is the renderer for the chat contact - * list. + * The ChatContactCellRenderer is the renderer for the chat room + * contact list. * * @author Yana Stamcheva + * @author Valentin Martinet */ public class ChatContactCellRenderer extends ContactListCellRenderer @@ -36,6 +41,7 @@ public class ChatContactCellRenderer * * @return this panel */ + @Override public Component getListCellRendererComponent( JList list, Object value, int index, @@ -46,7 +52,9 @@ public Component getListCellRendererComponent( JList list, this.rightLabel.setIcon(null); - ChatContact chatContact = (ChatContact) value; + final ChatContact chatContact = (ChatContact) value; + final ChatRoomMember member + = (ChatRoomMember) chatContact.getDescriptor(); this.setPreferredSize(new Dimension(20, 30)); @@ -61,8 +69,9 @@ public Component getListCellRendererComponent( JList list, this.nameLabel.setFont(this.getFont().deriveFont(Font.PLAIN)); this.nameLabel.setText(displayName); -// statusIcon.setImage(Constants.getStatusIcon(); -// this.nameLabel.setIcon(statusIcon); + if(member.getRole() != null) + this.nameLabel.setIcon( + ChatContactRoleIcon.getRoleIcon(member.getRole())); if (contactForegroundColor != null) this.nameLabel.setForeground(contactForegroundColor); @@ -73,6 +82,51 @@ public Component getListCellRendererComponent( JList list, if (avatar != null) this.rightLabel.setIcon(avatar); + else + { + if(chatContact.getName().equals( + member.getChatRoom().getUserNickname())) + { + // Try to retrieve local user avatar: + OperationSetServerStoredAccountInfo opSet + = (OperationSetServerStoredAccountInfo) + member.getChatRoom().getParentProvider().getOperationSet( + OperationSetServerStoredAccountInfo.class); + + Iterator itr = opSet.getAllAvailableDetails(); + while(itr.hasNext()) + { + GenericDetail detail = itr.next(); + if(detail instanceof BinaryDetail) + { + BinaryDetail bin = (BinaryDetail)detail; + if(bin.getBytes() != null) + this.rightLabel.setIcon( + ImageUtils.getScaledRoundedIcon( + bin.getBytes(), 25, 25)); + break; + } + } + ChatRoomMemberRole role = member.getChatRoom().getUserRole(); + if (role != null) + this.nameLabel.setIcon( + ChatContactRoleIcon.getRoleIcon(role)); + } + else + { + // Try to retrieve participant avatar: + OperationSetPersistentPresence opSet + = (OperationSetPersistentPresence) + member.getChatRoom().getParentProvider().getOperationSet( + OperationSetPersistentPresence.class); + + Contact c = opSet.findContactByID(member.getContactAddress()); + + if(opSet != null && c != null && c.getImage() != null) + this.rightLabel.setIcon(ImageUtils.getScaledRoundedIcon( + c.getImage(), 25, 25)); + } + } // We should set the bounds of the cell explicitly in order to // make getComponentAt work properly. diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatContactRoleIcon.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatContactRoleIcon.java new file mode 100644 index 000000000..d1e50d46e --- /dev/null +++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatContactRoleIcon.java @@ -0,0 +1,53 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.gui.main.chat.conference; + +import javax.swing.*; +import net.java.sip.communicator.impl.gui.utils.ImageLoader; +import net.java.sip.communicator.service.protocol.*; + +/** + * Allows to determine which icon should be chosen for the chat contact + * currently participating in a chatroom, regarding to his associated role. + * + * @author Valentin Martinet + */ +public class ChatContactRoleIcon +{ + /** + * Returns the role icon which corresponds to the given role. + * + * @param role the role to analyse + * @return Icon the associated Icon with this role + */ + public static Icon getRoleIcon(ChatRoomMemberRole role) + { + Icon i = null; + + switch(role) + { + case OWNER: i = new ImageIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_OWNER)); + break; + case ADMINISTRATOR: i = new ImageIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_ADMIN)); + break; + case MODERATOR: i = new ImageIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_MODERATOR)); + break; + case MEMBER: i = new ImageIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_STANDARD)); + break; + case GUEST: i = new ImageIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_GUEST)); + break; + default: i = new ImageIcon( + ImageLoader.getImage(ImageLoader.CHATROOM_MEMBER_SILENT)); + } + return i; + } +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomConfigurationWindow.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomConfigurationWindow.java index 68c81d94a..fd342f640 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomConfigurationWindow.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomConfigurationWindow.java @@ -19,48 +19,86 @@ import net.java.sip.communicator.util.swing.*; /** - * The configuration window for the chat room. - * + * The configuration window for a chat room. + * * @author Yana Stamcheva + * @author Valentin Martinet */ public class ChatRoomConfigurationWindow extends SIPCommFrame implements ActionListener { + /** + * The configuration form contained in this window. + */ private ChatRoomConfigurationForm configForm; + /** + * The scroll pane contained in the "General" tab. + */ private JScrollPane generalScrollPane = new JScrollPane(); + + /** + * The scroll pane contained in the "Options" tab. + */ private JScrollPane optionsScrollPane = new JScrollPane(); + /** + * The main panel. + */ private JPanel mainPanel = new JPanel(); + /** + * The button that stores the data. + */ private JButton saveButton = new JButton( GuiActivator.getResources().getI18NString("service.gui.APPLY")); + /** + * The cancel button. + */ private JButton cancelButton = new JButton( GuiActivator.getResources().getI18NString("service.gui.CANCEL")); + /** + * The panel contained in the "Options" tab. + */ private JPanel roomOptionsPanel = new JPanel(new GridLayout(0, 1)); + /** + * The panel containing all buttons. + */ private JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + /** + * The tabbed pane containing the "General" and "Options" tabs. + */ private JTabbedPane tabbedPane = new SIPCommTabbedPane(false, false); + /** + * The panel containing the title. + */ private TitlePanel titlePanel = new TitlePanel(); + /** + * A map all configuration components. + */ private Hashtable uiFieldsTable = new Hashtable(); /** * Creates an instance of ChatRoomConfigurationWindow and * initializes the configuration form. - * + * + * @param chatRoomName the name of the room * @param configForm the configuration form to load in this configuration * window */ public ChatRoomConfigurationWindow(String chatRoomName, ChatRoomConfigurationForm configForm) { + super(false); + this.configForm = configForm; this.setTitle(GuiActivator.getResources().getI18NString( @@ -105,6 +143,14 @@ public ChatRoomConfigurationWindow(String chatRoomName, this.getContentPane().add(tabbedPane, BorderLayout.CENTER); this.getContentPane().add(buttonsPanel, BorderLayout.SOUTH); + titlePanel.setOpaque(false); + tabbedPane.setOpaque(false); + buttonsPanel.setOpaque(false); + roomOptionsPanel.setOpaque(false); + optionsScrollPane.setOpaque(false); + mainPanel.setOpaque(false); + generalScrollPane.setOpaque(false); + this.roomOptionsPanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(15, 15, 15, 15), BorderFactory.createTitledBorder( @@ -113,7 +159,7 @@ public ChatRoomConfigurationWindow(String chatRoomName, this.loadConfigurationForm(); } - + /** * Loads the configuration form obtained from the chat room. */ @@ -278,6 +324,7 @@ else if(fieldType.equals( else { JPanel fieldPanel = new JPanel(new BorderLayout()); + fieldPanel.setOpaque(false); fieldPanel.setBorder( BorderFactory.createEmptyBorder(0, 0, 10, 0)); @@ -290,7 +337,7 @@ else if(fieldType.equals( } } } - + /** * Computes the maximum width of a label in the configuration form. * @@ -327,7 +374,8 @@ private int computeLabelWidth(ChatRoomConfigurationForm configForm) } /** - * + * Saves all configuration settings when the "Save" button is pressed. + * @param e the ActionEvent that notified us of the button action */ public void actionPerformed(ActionEvent e) { @@ -398,10 +446,10 @@ public void run() { new ErrorDialog( ChatRoomConfigurationWindow.this, - GuiActivator.getResources() - .getI18NString("service.gui.ERROR"), GuiActivator.getResources().getI18NString( - "service.gui.CHAT_ROOM_CONFIGURATION_SUBMIT_FAILED"), + "service.gui.ERROR"), + GuiActivator.getResources().getI18NString( + "service.gui.CHAT_ROOM_CONFIGURATION_SUBMIT_FAILED"), e).showDialog(); } } @@ -411,7 +459,5 @@ public void run() this.dispose(); } - protected void close(boolean isEscaped) - { - } + protected void close(boolean isEscaped) {} } diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomMemberListPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomMemberListPanel.java index c150b5dcf..ee7d4a57f 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomMemberListPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomMemberListPanel.java @@ -7,6 +7,7 @@ package net.java.sip.communicator.impl.gui.main.chat.conference; import java.awt.*; +import java.awt.event.*; import javax.swing.*; @@ -27,26 +28,44 @@ public class ChatRoomMemberListPanel extends JPanel { + /** + * The list of members. + */ private final DefaultContactList memberList = new DefaultContactList(); + /** + * The model of the members list. + */ private final ChatContactListModel memberListModel = new ChatContactListModel(); - // private final ChatPanel chatPanel; + private final ChatPanel chatPanel; /** * Creates an instance of ChatContactListPanel. * @param chat Currently not used */ - public ChatRoomMemberListPanel(ChatPanel chat) + public ChatRoomMemberListPanel(final ChatPanel chat) { super(new BorderLayout()); - // this.chatPanel = chat; + this.chatPanel = chat; this.memberList.setModel(memberListModel); this.memberList.addKeyListener(new CListKeySearchListener(memberList)); this.memberList.setCellRenderer(new ChatContactCellRenderer()); + this.memberList.addMouseListener(new MouseAdapter() + { + public void mouseClicked(MouseEvent e) + { + if(e.getButton() == MouseEvent.BUTTON3) + { + new ChatContactRightButtonMenu( + chat, (ChatContact)memberList.getSelectedValue()).show( + memberList, e.getX(), e.getY()); + } + } + }); JScrollPane contactsScrollPane = new SCScrollPane(); contactsScrollPane.setHorizontalScrollBarPolicy( diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomSubjectPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomSubjectPanel.java index 662bdb44e..86656548e 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomSubjectPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ChatRoomSubjectPanel.java @@ -17,6 +17,7 @@ import net.java.sip.communicator.impl.gui.utils.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.swing.*; /** * The panel containing the subject of the chat room and the configuration @@ -25,25 +26,40 @@ * @author Yana Stamcheva */ public class ChatRoomSubjectPanel - extends JPanel + extends TransparentPanel { + /** + * The object used for logging. + */ private Logger logger = Logger.getLogger(ChatRoomSubjectPanel.class); + /** + * The panel containing the subject of the chat room. + */ private JLabel subjectLabel = new JLabel( GuiActivator.getResources().getI18NString("service.gui.SUBJECT") + ": "); + /** + * The field containing the subject of the chat room. + */ private JTextField subjectField = new JTextField(); + /** + * The button that opens the configuration form of the chat room. + */ private JButton configButton = new JButton(new ImageIcon( - ImageLoader.getImage(ImageLoader.QUICK_MENU_CONFIGURE_ICON))); + ImageLoader.getImage(ImageLoader.CHAT_ROOM_CONFIG))); + /** + * The corresponding chat session. + */ private ConferenceChatSession chatSession; /** * The parent window. */ private ChatWindow chatWindow; - + /** * Creates the panel containing the chat room subject. * @@ -86,14 +102,16 @@ public void setSubject(String subject) this.subjectField.setText(subject); } - /* + /** * Opens the configuration dialog when the configure buttons is pressed. */ - private class ConfigButtonActionListener implements ActionListener + private class ConfigButtonActionListener + implements ActionListener { /** * Obtains and opens the configuration form of the corresponding chat * room when user clicks on the configuration button. + * @param evt the ActionEvent that notified us */ public void actionPerformed(ActionEvent evt) { @@ -106,14 +124,14 @@ public void actionPerformed(ActionEvent evt) = new ChatRoomConfigurationWindow( chatSession.getChatName(), configForm); + configWindow.pack(); configWindow.setVisible(true); } catch (OperationFailedException e) { logger.error( - "Failed to obtain the chat room configuration form.", - e); - + "Failed to obtain the chat room configuration form.", e); + if(e.getErrorCode() == OperationFailedException.NOT_ENOUGH_PRIVILEGES) { diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java index f83fdcdda..f8c9dbb24 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatManager.java @@ -46,19 +46,37 @@ public class ConferenceChatManager LocalUserAdHocChatRoomPresenceListener, ServiceListener { + /** + * The object used for logging. + */ private static final Logger logger = Logger.getLogger(ConferenceChatManager.class); + /** + * Maps each history window to a ChatRoomWrapper. + */ private final Hashtable chatRoomHistory = new Hashtable(); + /** + * The list of persistent chat rooms. + */ private final ChatRoomList chatRoomList = new ChatRoomList(); - + + /** + * The list of ad-hoc chat rooms. + */ private final AdHocChatRoomList adHocChatRoomList = new AdHocChatRoomList(); + /** + * A list of all ChatRoomListChangeListener-s. + */ private final Vector listChangeListeners = new Vector(); + /** + * A list of all AdHocChatRoomListChangeListener-s. + */ private final Vector adHoclistChangeListeners = new Vector(); @@ -90,7 +108,7 @@ public ChatRoomList getChatRoomList() { return chatRoomList; } - + /** * Returns all chat room providers currently contained in the ad-hoc chat * room list. @@ -117,15 +135,15 @@ public void invitationReceived(ChatRoomInvitationReceivedEvent evt) dialog.setVisible(true); } - public void invitationRejected(ChatRoomInvitationRejectedEvent evt) - { - } + public void invitationRejected(ChatRoomInvitationRejectedEvent evt) {} /** * Implements the ChatRoomMessageListener.messageDelivered method. *
* Shows the message in the conversation area and clears the write message * area. + * @param evt the ChatRoomMessageDeliveredEvent that notified us + * that the message was delivered to its destination */ public void messageDelivered(ChatRoomMessageDeliveredEvent evt) { @@ -175,6 +193,8 @@ public void messageDelivered(ChatRoomMessageDeliveredEvent evt) *
* Obtains the corresponding ChatPanel and process the message * there. + * @param evt the ChatRoomMessageReceivedEvent that notified us + * that a message has been received */ public void messageReceived(ChatRoomMessageReceivedEvent evt) { @@ -316,6 +336,8 @@ static boolean isPrivate(ChatRoom chatRoom) * method. *
* In the conversation area shows an error message, explaining the problem. + * @param evt the ChatRoomMessageDeliveryFailedEvent that notified + * us of a delivery failure */ public void messageDeliveryFailed(ChatRoomMessageDeliveryFailedEvent evt) { @@ -390,7 +412,8 @@ else if (evt.getErrorCode() * LocalUserAdHocChatRoomPresenceListener.localUserPresenceChanged * method * - * @param evt + * @param evt the LocalUserAdHocChatRoomPresenceChangeEvent that + * notified us of a presence change */ public void localUserAdHocPresenceChanged( LocalUserAdHocChatRoomPresenceChangeEvent evt) @@ -462,6 +485,8 @@ else if (LocalUserAdHocChatRoomPresenceChangeEvent * Implements the * LocalUserChatRoomPresenceListener.localUserPresenceChanged * method. + * @param evt the LocalUserChatRoomPresenceChangeEvent that + * notified us */ public void localUserPresenceChanged( LocalUserChatRoomPresenceChangeEvent evt) @@ -558,9 +583,9 @@ public void acceptInvitation(ChatRoomInvitation invitation) * Called to accept an incoming invitation. Adds the invitation chat room * to the list of chat rooms and joins it. * - * @param invitation the invitation to accept. - * - * @throws OperationFailedException + * @param invitation the invitation to accept + * @param multiUserChatOpSet the operation set for chat conferencing + * @throws OperationFailedException if the accept fails */ public void acceptInvitation( AdHocChatRoomInvitation invitation, @@ -637,13 +662,30 @@ public void joinChatRoom( ChatRoomWrapper chatRoomWrapper, * Creates a chat room, by specifying the chat room name, the parent * protocol provider and eventually, the contacts invited to participate in * this chat room. - * - * @param chatRoomName the name of the chat room to create. + * + * @param protocolProvider the parent protocol provider. + * @param contacts the contacts invited when creating the chat room. + * @return the ChatRoomWrapper corresponding to the created room + */ + public ChatRoomWrapper createChatRoom( + ProtocolProviderService protocolProvider, + Collection contacts) + { + return this.createChatRoom(null, protocolProvider, contacts); + } + + /** + * Creates a chat room, by specifying the chat room name, the parent + * protocol provider and eventually, the contacts invited to participate in + * this chat room. + * + * @param roomName the name of the room * @param protocolProvider the parent protocol provider. * @param contacts the contacts invited when creating the chat room. + * @return the ChatRoomWrapper corresponding to the created room */ public ChatRoomWrapper createChatRoom( - String chatRoomName, + String roomName, ProtocolProviderService protocolProvider, Collection contacts) { @@ -663,13 +705,12 @@ public ChatRoomWrapper createChatRoom( OperationSetPersistentPresence opSet = protocolProvider .getOperationSet(OperationSetPersistentPresence.class); - + for(String contact : contacts) - { members.put(contact, opSet.findContactByID(contact)); - } - - chatRoom = groupChatOpSet.createChatRoom(chatRoomName, members); + + // We don't specify the name of the room for now. + chatRoom = groupChatOpSet.createChatRoom(roomName, members); } catch (OperationFailedException ex) { @@ -680,7 +721,7 @@ public ChatRoomWrapper createChatRoom( GuiActivator.getResources().getI18NString("service.gui.ERROR"), GuiActivator.getResources().getI18NString( "service.gui.CREATE_CHAT_ROOM_ERROR", - new String[]{chatRoomName}), + new String[]{protocolProvider.getProtocolName()}), ex) .showDialog(); } @@ -693,7 +734,7 @@ public ChatRoomWrapper createChatRoom( GuiActivator.getResources().getI18NString("service.gui.ERROR"), GuiActivator.getResources().getI18NString( "service.gui.CREATE_CHAT_ROOM_ERROR", - new String[]{chatRoomName}), + new String[]{protocolProvider.getProtocolName()}), ex) .showDialog(); } @@ -718,13 +759,13 @@ public ChatRoomWrapper createChatRoom( * Creates an ad-hoc chat room, by specifying the ad-hoc chat room name, the * parent protocol provider and eventually, the contacts invited to * participate in this ad-hoc chat room. - * - * @param chatRoomName the name of the chat room to create. + * * @param protocolProvider the parent protocol provider. * @param contacts the contacts invited when creating the chat room. + * @return the AdHocChatRoomWrapper corresponding to the created + * ad hoc chat room */ public AdHocChatRoomWrapper createAdHocChatRoom( - String chatRoomName, ProtocolProviderService protocolProvider, Collection contacts) { @@ -737,9 +778,9 @@ public AdHocChatRoomWrapper createAdHocChatRoom( // If there's no group chat operation set we have nothing to do here. if (groupChatOpSet == null) return null; - + AdHocChatRoom chatRoom = null; - + try { List members = new LinkedList(); @@ -752,17 +793,16 @@ public AdHocChatRoomWrapper createAdHocChatRoom( members.add(opSet.findContactByID(contact)); } - chatRoom = groupChatOpSet.createAdHocChatRoom( - chatRoomName, members); + chatRoom = groupChatOpSet.createAdHocChatRoom(null, members); } catch (OperationFailedException ex) - { + { new ErrorDialog( GuiActivator.getUIService().getMainFrame(), GuiActivator.getResources().getI18NString("service.gui.ERROR"), GuiActivator.getResources().getI18NString( "service.gui.CREATE_CHAT_ROOM_ERROR", - new String[]{chatRoomName}), + new String[]{protocolProvider.getProtocolName()}), ex) .showDialog(); } @@ -773,7 +813,7 @@ public AdHocChatRoomWrapper createAdHocChatRoom( GuiActivator.getResources().getI18NString("service.gui.ERROR"), GuiActivator.getResources().getI18NString( "service.gui.CREATE_CHAT_ROOM_ERROR", - new String[]{chatRoomName}), + new String[]{protocolProvider.getProtocolName()}), ex) .showDialog(); } @@ -782,8 +822,8 @@ public AdHocChatRoomWrapper createAdHocChatRoom( { AdHocChatRoomProviderWrapper parentProvider = adHocChatRoomList.findServerWrapperFromProvider( - protocolProvider); - + protocolProvider); + chatRoomWrapper = new AdHocChatRoomWrapper( parentProvider, chatRoom); parentProvider.addAdHocChatRoom(chatRoomWrapper); @@ -845,7 +885,7 @@ public void joinChatRoom(AdHocChatRoomWrapper chatRoomWrapper) new JoinAdHocChatRoomTask(chatRoomWrapper).execute(); } - + /** * Removes the given chat room from the UI. * @@ -942,12 +982,14 @@ public void joinChatRoom(AdHocChatRoom chatRoom) chatWindowManager.getMultiChat(chatRoomWrapper, true), true); } - + /** * Joins the given chat room and manages all the exceptions that could * occur during the join process. * * @param chatRoom the chat room to join + * @param nickname the nickname we're using to join + * @param password the password we're using to join */ public void joinChatRoom( ChatRoom chatRoom, String nickname, @@ -1082,6 +1124,12 @@ public void leaveChatRoom(AdHocChatRoomWrapper chatRoomWrapper) } } + /** + * Returns existing chat rooms for the given chatRoomProvider. + * @param chatRoomProvider the ChatRoomProviderWrapper, which + * chat rooms we're looking for + * @return existing chat rooms for the given chatRoomProvider + */ public List getExistingChatRooms( ChatRoomProviderWrapper chatRoomProvider) { @@ -1214,6 +1262,9 @@ public void removeAdHocChatRoomListChangeListener( /** * Notifies all interested listeners that a change in the chat room list * model has occurred. + * @param chatRoomWrapper the chat room wrapper that identifies the chat + * room + * @param eventID the identifier of the event */ private void fireChatRoomListChangedEvent( ChatRoomWrapper chatRoomWrapper, int eventID) @@ -1226,10 +1277,13 @@ private void fireChatRoomListChangedEvent( ChatRoomWrapper chatRoomWrapper, l.contentChanged(evt); } } - + /** * Notifies all interested listeners that a change in the chat room list * model has occurred. + * @param adHocChatRoomWrapper the chat room wrapper that identifies the + * chat room + * @param eventID the identifier of the event */ private void fireAdHocChatRoomListChangedEvent( AdHocChatRoomWrapper adHocChatRoomWrapper, @@ -1293,18 +1347,14 @@ public void serviceChanged(ServiceEvent event) // know if (event.getServiceReference().getBundle().getState() == Bundle.STOPPING) - { return; - } Object service = GuiActivator.bundleContext.getService(event .getServiceReference()); // we don't care if the source service is not a protocol provider if (!(service instanceof ProtocolProviderService)) - { return; - } ProtocolProviderService protocolProvider = (ProtocolProviderService) service; @@ -1312,7 +1362,7 @@ public void serviceChanged(ServiceEvent event) Object multiUserChatOpSet = protocolProvider .getOperationSet(OperationSetMultiUserChat.class); - + Object multiUserChatAdHocOpSet = protocolProvider .getOperationSet(OperationSetAdHocMultiUserChat.class); @@ -1339,12 +1389,6 @@ else if (event.getType() == ServiceEvent.UNREGISTERING) chatRoomList.removeChatProvider(protocolProvider); } } - else - { - return; - } - - } /** @@ -1388,6 +1432,7 @@ private static class JoinChatRoomTask /** * @override {@link SwingWorker}{@link #doInBackground()} to perform * all asynchronous tasks. + * @return SUCCESS if success, otherwise the error code */ public String doInBackground() { @@ -1528,6 +1573,7 @@ private static class JoinAdHocChatRoomTask /** * @override {@link SwingWorker}{@link #doInBackground()} to perform * all asynchronous tasks. + * @return SUCCESS if success, otherwise the error code */ public String doInBackground() { @@ -1638,6 +1684,7 @@ private static class FindRoomTask /** * @override {@link SwingWorker}{@link #doInBackground()} to perform * all asynchronous tasks. + * @return the chat room */ public ChatRoom doInBackground() { @@ -1674,6 +1721,7 @@ private static class FindAllRoomsTask /** * @override {@link SwingWorker}{@link #doInBackground()} to perform * all asynchronous tasks. + * @return a list of existing chat rooms */ public List doInBackground() { @@ -1709,7 +1757,14 @@ public List doInBackground() } } - public void invitationReceived(AdHocChatRoomInvitationReceivedEvent evt) { + /** + * Indicates that an invitation has been received and opens the invitation + * dialog to notify the user. + * @param evt the AdHocChatRoomInvitationReceivedEvent that + * notified us + */ + public void invitationReceived(AdHocChatRoomInvitationReceivedEvent evt) + { logger.info("Invitation received: "+evt.toString()); OperationSetAdHocMultiUserChat multiUserChatOpSet = evt.getSourceOperationSet(); @@ -1726,6 +1781,8 @@ public void invitationReceived(AdHocChatRoomInvitationReceivedEvent evt) { *
* Shows the message in the conversation area and clears the write message * area. + * @param evt the AdHocChatRoomMessageDeliveredEvent that notified + * us */ public void messageDelivered(AdHocChatRoomMessageDeliveredEvent evt) { @@ -1778,6 +1835,8 @@ public void messageDelivered(AdHocChatRoomMessageDeliveredEvent evt) * method. *
* In the conversation area shows an error message, explaining the problem. + * @param evt the AdHocChatRoomMessageDeliveryFailedEvent that + * notified us */ public void messageDeliveryFailed( AdHocChatRoomMessageDeliveryFailedEvent evt) @@ -1842,6 +1901,8 @@ else if (evt.getErrorCode() *
* Obtains the corresponding ChatPanel and process the message * there. + * @param evt the AdHocChatRoomMessageReceivedEvent that notified + * us */ public void messageReceived(AdHocChatRoomMessageReceivedEvent evt) { @@ -1911,7 +1972,5 @@ public void messageReceived(AdHocChatRoomMessageReceivedEvent evt) } - public void invitationRejected(AdHocChatRoomInvitationRejectedEvent evt) - { - } + public void invitationRejected(AdHocChatRoomInvitationRejectedEvent evt) {} } diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatSession.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatSession.java index cf505407b..46ec6c255 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatSession.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatSession.java @@ -28,18 +28,37 @@ public class ConferenceChatSession ChatRoomMemberPresenceListener, ChatRoomPropertyChangeListener { + /** + * The list of all chat participants. + */ private final List chatParticipants = new ArrayList(); + /** + * The list of available chat transports. + */ private final List chatTransports = new ArrayList(); + /** + * The current chat transport used for messaging. + */ private ChatTransport currentChatTransport; + /** + * The chat room wrapper, which is the descriptor of this chat session. + */ private final ChatRoomWrapper chatRoomWrapper; + /** + * The object used for rendering. + */ private final ChatSessionRenderer sessionRenderer; - + + /** + * The list of all ChatSessionChangeListener-s registered to listen + * for transport modifications. + */ private final java.util.List chatTransportChangeListeners = new Vector(); @@ -90,6 +109,7 @@ public void dispose() ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); chatRoom.removeMemberPresenceListener(this); chatRoom.removePropertyChangeListener(this); + chatRoom.leave(); } /** @@ -362,8 +382,7 @@ public void setCurrentChatTransport(ChatTransport chatTransport) * @param smsPhoneNumber The default mobile number used to send sms-es in * this session. */ - public void setDefaultSmsNumber(String smsPhoneNumber) - {} + public void setDefaultSmsNumber(String smsPhoneNumber) {} /** * Returns the ChatSessionRenderer that provides the connection @@ -382,6 +401,8 @@ public ChatSessionRenderer getChatSessionRenderer() * list of chat participants on the right of the chat window. When a * ChatRoomMember has left or quit, or has being kicked it's * removed from the chat window. + * @param evt the ChatRoomMemberPresenceChangeEvent that notified + * us */ public void memberPresenceChanged(ChatRoomMemberPresenceChangeEvent evt) { @@ -397,6 +418,20 @@ public void memberPresenceChanged(ChatRoomMemberPresenceChangeEvent evt) if (eventType.equals(ChatRoomMemberPresenceChangeEvent.MEMBER_JOINED)) { + // Check if not ever present in the chat room. In some cases, the + // considered chatroom member may appear twice in the chat contact + // list panel. + for(int i=0; iChatTransport corresponding to the given + * descriptor. + * @param descriptor the descriptor of the chat transport we're looking for + * @return the ChatTransport corresponding to the given + * descriptor + */ public ChatTransport findChatTransportForDescriptor(Object descriptor) { return MetaContactChatSession.findChatTransportForDescriptor( @@ -559,7 +600,12 @@ private void initChatParticipants() } } - /* Implements ChatSession#isContactListSupported(). */ + /** + * Indicates if the contact list is supported by this session. The contact + * list would be supported for all non system and non private sessions. + * @return true to indicate that the contact list is supported, + * false otherwise. + */ public boolean isContactListSupported() { ChatRoom chatRoom = chatRoomWrapper.getChatRoom(); @@ -568,7 +614,12 @@ public boolean isContactListSupported() !chatRoom.isSystem() && !ConferenceChatManager.isPrivate(chatRoom); } - + + /** + * Adds the given ChatSessionChangeListener to the list of + * transport listeners. + * @param l the listener to add + */ public void addChatTransportChangeListener(ChatSessionChangeListener l) { synchronized (chatTransportChangeListeners) @@ -577,7 +628,12 @@ public void addChatTransportChangeListener(ChatSessionChangeListener l) chatTransportChangeListeners.add(l); } } - + + /** + * Removes the given ChatSessionChangeListener from contained + * transport listeners. + * @param l the listener to remove + */ public void removeChatTransportChangeListener(ChatSessionChangeListener l) { synchronized (chatTransportChangeListeners) @@ -585,4 +641,24 @@ public void removeChatTransportChangeListener(ChatSessionChangeListener l) chatTransportChangeListeners.remove(l); } } + + /** + * Adds the given ChatRoomMemberRoleListener to the contained + * chat room role listeners. + * @param l the listener to add + */ + public void addMemberRoleListener(ChatRoomMemberRoleListener l) + { + chatRoomWrapper.getChatRoom().addMemberRoleListener(l); + } + + /** + * Adds the given ChatRoomLocalUserRoleListener to the contained + * chat room role listeners. + * @param l the listener to add + */ + public void addLocalUserRoleListener(ChatRoomLocalUserRoleListener l) + { + chatRoomWrapper.getChatRoom().addLocalUserRoleListener(l); + } } diff --git a/src/net/java/sip/communicator/impl/gui/main/chatroomslist/ChatRoomList.java b/src/net/java/sip/communicator/impl/gui/main/chatroomslist/ChatRoomList.java index 7d2beed57..6e0e2e869 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chatroomslist/ChatRoomList.java +++ b/src/net/java/sip/communicator/impl/gui/main/chatroomslist/ChatRoomList.java @@ -82,9 +82,7 @@ public void addChatProvider(ProtocolProviderService pps) = new ChatRoomProviderWrapper(pps); providersList.add(chatRoomProvider); - - - + ConfigurationService configService = GuiActivator.getConfigurationService(); diff --git a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java index 05b58a451..a0c3e5b73 100644 --- a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java +++ b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java @@ -748,6 +748,12 @@ public class ImageLoader public static final ImageID CALL_PEER_TOOLS = new ImageID("service.gui.buttons.CALL_PEER_TOOLS"); + /** + * The icon used for the chat room configuration button. + */ + public static final ImageID CHAT_ROOM_CONFIG + = new ImageID("service.gui.buttons.CHAT_ROOM_CONFIG"); + /* * ======================================================================= * ------------------------ EDIT TOOLBAR ICONS --------------------------- @@ -1060,6 +1066,66 @@ public class ImageLoader public static final ImageID USER_OCCUPIED_ICON = new ImageID("service.gui.statusicons.USER_OCCUPIED_ICON"); + /** + * Owner chatroom member. + */ + public static final ImageID CHATROOM_MEMBER_OWNER + = new ImageID("service.gui.icons.CHATROOM_MEMBER_OWNER"); + + /** + * Admin chatroom member. + */ + public static final ImageID CHATROOM_MEMBER_ADMIN + = new ImageID("service.gui.icons.CHATROOM_MEMBER_ADMIN"); + + /** + * Moderator chatroom member. + */ + public static final ImageID CHATROOM_MEMBER_MODERATOR + = new ImageID("service.gui.icons.CHATROOM_MEMBER_MODERATOR"); + + /** + * Standard chatroom member. + */ + public static final ImageID CHATROOM_MEMBER_STANDARD + = new ImageID("service.gui.icons.CHATROOM_MEMBER_STANDARD"); + + /** + * Guest chatroom member. + */ + public static final ImageID CHATROOM_MEMBER_GUEST + = new ImageID("service.gui.icons.CHATROOM_MEMBER_GUEST"); + + /** + * Silent chatroom member. + */ + public static final ImageID CHATROOM_MEMBER_SILENT + = new ImageID("service.gui.icons.CHATROOM_MEMBER_SILENT"); + + /** + * Change room icon. + */ + public static final ImageID CHANGE_ROOM_SUBJECT_ICON_16x16 + = new ImageID("service.gui.icons.CHANGE_ROOM_SUBJECT_16x16"); + + /** + * Change nickname icon + */ + public static final ImageID CHANGE_NICKNAME_ICON_16x16 + = new ImageID("service.gui.icons.CHANGE_NICKNAME_16x16"); + + /** + * Ban icon. + */ + public static final ImageID BAN_ICON_16x16 + = new ImageID("service.gui.icons.BAN_16x16"); + + /** + * Kick icon. + */ + public static final ImageID KICK_ICON_16x16 + = new ImageID("service.gui.icons.KICK_16x16"); + /* * ===================================================================== * ---------------------------- SOUND LEVEL ICONS ---------------------- diff --git a/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java b/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java index 83ed9717f..fd97bf60d 100644 --- a/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java +++ b/src/net/java/sip/communicator/impl/msghistory/MessageHistoryServiceImpl.java @@ -50,8 +50,8 @@ public class MessageHistoryServiceImpl private static Logger logger = Logger .getLogger(MessageHistoryServiceImpl.class); - private static String[] STRUCTURE_NAMES = - new String[] { "dir", "msg_CDATA", "msgTyp", "enc", "uid", "sub", + private static String[] STRUCTURE_NAMES + = new String[] { "dir", "msg_CDATA", "msgTyp", "enc", "uid", "sub", "receivedTimestamp" }; private static HistoryRecordStructure recordStructure = @@ -80,6 +80,10 @@ public class MessageHistoryServiceImpl private static ResourceManagementService resourcesService; + /** + * Returns the history service. + * @return the history service + */ public HistoryService getHistoryService() { return historyService; @@ -664,7 +668,7 @@ private EventObject convertHistoryRecordToMessageEvent( HistoryRecord hr, * which are returned by the finder methods * * @param hr HistoryRecord - * @param contact Contact + * @param room the chat room * @return Object */ private EventObject convertHistoryRecordToMessageEvent( @@ -763,7 +767,7 @@ else if (propName.equals(STRUCTURE_NAMES[6])) } /** - * starts the service. Check the current registerd protocol providers + * Starts the service. Check the current registered protocol providers * which supports BasicIM and adds message listener to them * * @param bc BundleContext @@ -817,7 +821,7 @@ public void start(BundleContext bc) } /** - * stops the service. + * Stops the service. * * @param bc BundleContext */ @@ -2020,7 +2024,7 @@ static class ChatRoomMemberImpl { private final ChatRoom chatRoom; private final String name; - private final ChatRoomMemberRole role; + private ChatRoomMemberRole role; public ChatRoomMemberImpl(String name, ChatRoom chatRoom, ChatRoomMemberRole role) @@ -2060,6 +2064,11 @@ public byte[] getAvatar() return null; } + public void setRole(ChatRoomMemberRole newRole) + { + this.role = newRole; + } + public Contact getContact() { return null; diff --git a/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomIrcImpl.java b/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomIrcImpl.java index dc691a3c6..ac86cc832 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomIrcImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomIrcImpl.java @@ -24,9 +24,12 @@ public class ChatRoomIrcImpl implements ChatRoom { + /** + * The object used for logging. + */ private static final Logger logger = Logger.getLogger(ChatRoomIrcImpl.class); - + /** * The name of the chat room. */ @@ -89,8 +92,9 @@ public class ChatRoomIrcImpl * Listeners that will be notified every time * a chat room member property has been changed. */ - private Vector memberPropChangeListeners - = new Vector(); + private Vector + memberPropChangeListeners + = new Vector(); /** * The table containing all banned members. @@ -136,6 +140,7 @@ public ChatRoomIrcImpl( String chatRoomName, * @param chatRoomName the name of the chat room * @param parentProvider the protocol provider * @param isPrivate indicates if this chat room is a private one + * @param isSystem indicates if this chat room is a system room */ public ChatRoomIrcImpl( String chatRoomName, ProtocolProviderServiceIrcImpl parentProvider, @@ -586,6 +591,7 @@ public void removeMessageListener(ChatRoomMessageListener listener) /** * Adds a ChatRoomMember to the list of members of this chat room. * + * @param memberID the identifier of the member * @param member the ChatRoomMember to add. */ protected void addChatRoomMember(String memberID, ChatRoomMember member) @@ -1023,25 +1029,24 @@ protected void setNickName(String nickName) /** * Sets the subject obtained from the server once we're connected. - * + * * @param subject the subject to set */ protected void setSubjectFromServer(String subject) { this.chatSubject = subject; } - + /** * Determines whether this chat room should be stored in the configuration * file or not. If the chat room is persistent it still will be shown after a * restart in the chat room list. A non-persistent chat room will be only in * the chat room list until the the program is running. - * + * * @return true if this chat room is persistent, false otherwise */ public boolean isPersistent() { - /* * Private ChatRooms are not persistent because they correspond to * conversations created by sending private messages and such @@ -1049,4 +1054,117 @@ public boolean isPersistent() */ return !isPrivate(); } + + /** + * Returns the local user role. + * @return the local user role + */ + public ChatRoomMemberRole getUserRole() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Sets the local user role. + * @param role the role to set + * @throws OperationFailedException if the operation don't succeed + */ + public void setUserRole(ChatRoomMemberRole role) + throws OperationFailedException + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Grants admin role to the participant given by address. + * @param address the address of the participant to grant admin role to + */ + public void grantAdmin(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Grants membership role to the participant given by address. + * @param address the address of the participant to grant membership role to + */ + public void grantMembership(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Grants moderator role to the participant given by address. + * @param address the address of the participant to grant moderator role to + */ + public void grantModerator(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Grants ownership role to the participant given by address. + * @param address the address of the participant to grant ownership role to + */ + public void grantOwnership(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Grants voice to the participant given by address. + * @param address the address of the participant to grant voice to + */ + public void grantVoice(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Revokes the admin role for the participant given by address. + * @param address the address of the participant to revoke admin role for + */ + public void revokeAdmin(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Revokes the membership role for the participant given by address. + * @param address the address of the participant to revoke membership role + * for + */ + public void revokeMembership(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Revokes the moderator role for the participant given by address. + * @param address the address of the participant to revoke moderator role + * for + */ + public void revokeModerator(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Revokes the ownership role for the participant given by address. + * @param address the address of the participant to revoke ownership role + * for + */ + public void revokeOwnership(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Revokes the voice for the participant given by address. + * @param address the address of the participant to revoke voice for + */ + public void revokeVoice(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } } diff --git a/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomMemberIrcImpl.java b/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomMemberIrcImpl.java index 471d3580b..9a0547eff 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomMemberIrcImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/ChatRoomMemberIrcImpl.java @@ -10,37 +10,27 @@ /** * Represents a chat room member. - * + * * @author Stephane Remy */ -public class ChatRoomMemberIrcImpl implements ChatRoomMember +public class ChatRoomMemberIrcImpl + implements ChatRoomMember { - /** * The ChatRoom. */ - private ChatRoom chatRoom = null; - + private final ChatRoom chatRoom; + /** * The id of the contact. */ - private String contactID = null; - - /** - * The login of the contact. - */ - private String login = null; - - /** - * The host name of the contact - */ - private String hostname = null; - + private final String contactID; + /** * The provider that created us. */ private ProtocolProviderServiceIrcImpl parentProvider = null; - + /** * The role of this member. */ @@ -56,26 +46,20 @@ public class ChatRoomMemberIrcImpl implements ChatRoomMember * chat room belongs * @param chatRoom the chat room, where this member is joined * @param contactID the nickname of the member - * @param login the login name of the member - * @param hostname the host name * @param chatRoomMemberRole the role that this member has in the * corresponding chat room */ public ChatRoomMemberIrcImpl(ProtocolProviderServiceIrcImpl parentProvider, ChatRoom chatRoom, String contactID, - String login, - String hostname, ChatRoomMemberRole chatRoomMemberRole) { this.parentProvider = parentProvider; this.chatRoom = chatRoom; this.contactID = contactID; - this.login = login; - this.hostname = hostname; this.chatRoomMemberRole = chatRoomMemberRole; } - + /** * Returns the chat room that this member is participating in. * @@ -134,13 +118,13 @@ public ChatRoomMemberRole getRole() { return this.chatRoomMemberRole; } - + /** * Sets a new member role to this ChatRoomMember. * * @param chatRoomMemberRole the role to be set */ - public void setChatRoomMemberRole(ChatRoomMemberRole chatRoomMemberRole) + public void setRole(ChatRoomMemberRole chatRoomMemberRole) { this.chatRoomMemberRole = chatRoomMemberRole; } diff --git a/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java b/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java index db0ecba27..abb724475 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/IrcStack.java @@ -86,7 +86,7 @@ public class IrcStack /** * Creates an instance of IrcStack. - * + * * @param parentProvider the IRC protocol provider service * @param nickname our nickname * @param login our login @@ -201,6 +201,11 @@ protected void onDisconnect() /** * Indicates that a message has arrived from the IRC stack. + * @param channel the channel where the message is received + * @param sender the sender of the message + * @param login the login + * @param hostname the host name + * @param messageContent the content of the message */ protected void onMessage( String channel, String sender, @@ -242,6 +247,10 @@ protected void onMessage( String channel, /** * Indicates that a private message has been received. * Note that for now this method only logs the message. + * @param sender the sender of the message + * @param login the login + * @param hostname the host name + * @param messageContent the content of the message */ protected void onPrivateMessage(String sender, String login, @@ -272,8 +281,6 @@ protected void onPrivateMessage(String sender, = new ChatRoomMemberIrcImpl(parentProvider, chatRoom, sender, - login, - hostname, ChatRoomMemberRole.GUEST); chatRoom.addChatRoomMember(sender, sourceMember); @@ -490,8 +497,6 @@ protected void onJoin( String channel, parentProvider, chatRoom, sender, - login, - hostname, ChatRoomMemberRole.GUEST); chatRoom.addChatRoomMember(sender, member); @@ -1527,8 +1532,6 @@ else if (userPrefix.contains("+")) = new ChatRoomMemberIrcImpl(parentProvider, chatRoom, user.getNick(), - null, - null, newMemberRole); chatRoom.addChatRoomMember(user.getNick(), newMember); @@ -1731,6 +1734,7 @@ else if (command.startsWith("/query")) * @param chatRoom the chat room for which the user should be banned * @param hostmask the host mask of the user to ban * @param reason the reason of the ban + * @throws OperationFailedException if something goes wrong */ protected void banParticipant( String chatRoom, String hostmask, @@ -1816,7 +1820,7 @@ private void onWhoIs(UserInfo userInfo) System.currentTimeMillis(), ChatRoomMessageReceivedEvent.SYSTEM_MESSAGE_RECEIVED); } - + /** * Adds a chat room to the server chat room list. * @@ -1838,7 +1842,7 @@ private void addServerChatRoom(String chatRoomName) private class JoinTimeoutTask extends TimerTask { private ChatRoom chatRoom; - + /** * Creates an instance of JoinTimeoutTask. * @@ -1885,6 +1889,7 @@ private void lockChatRoomOperation() /** * Notifies the waiting chat room operation. + * @param responseCode the response code of the operation to notify for */ private void notifyChatRoomOperation(int responseCode) { @@ -2006,7 +2011,11 @@ else if (operationResponseCode == ERR_ERRONEUSNICKNAME) "You need to enter a valid nickname.", OperationFailedException.ILLEGAL_ARGUMENT); } - + + /** + * Creates the chat room given by target. + * @param target the name of the chat room to create + */ protected void createPrivateChatRoom(String target) { ChatRoomIrcImpl privateChatRoom @@ -2024,8 +2033,6 @@ protected void createPrivateChatRoom(String target) parentProvider, privateChatRoom, parentProvider.getAccountID().getService(), - "", - "", ChatRoomMemberRole.GUEST); MessageIrcImpl queryMessage diff --git a/src/net/java/sip/communicator/impl/protocol/irc/OperationSetMultiUserChatIrcImpl.java b/src/net/java/sip/communicator/impl/protocol/irc/OperationSetMultiUserChatIrcImpl.java index baba58e21..3d50aea3c 100644 --- a/src/net/java/sip/communicator/impl/protocol/irc/OperationSetMultiUserChatIrcImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/irc/OperationSetMultiUserChatIrcImpl.java @@ -320,8 +320,6 @@ protected ChatRoomMemberIrcImpl findSystemMember() ircProvider, serverChatRoom, ircProvider.getAccountID().getService(), - "", // We don't specify a login. - "", // We don't specify a hostname. ChatRoomMemberRole.GUEST); } } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java index 412559c8e..985fa72ef 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomJabberImpl.java @@ -28,6 +28,7 @@ * * @author Emil Ivov * @author Yana Stamcheva + * @author Valentin Martinet */ public class ChatRoomJabberImpl implements ChatRoom @@ -98,12 +99,14 @@ public class ChatRoomJabberImpl /** * The list of members of this chat room. */ - private final Hashtable members = new Hashtable(); + private final Hashtable members + = new Hashtable(); /** * The list of banned members of this chat room. */ - private final Hashtable banList = new Hashtable(); + private final Hashtable banList + = new Hashtable(); /** * The nickname of this chat room local user participant. @@ -115,6 +118,11 @@ public class ChatRoomJabberImpl */ private String oldSubject; + /** + * The role of this chat room local user participant. + */ + private ChatRoomMemberRole role = null; + /** * The corresponding configuration form. */ @@ -131,17 +139,18 @@ public ChatRoomJabberImpl(MultiUserChat multiUserChat, ProtocolProviderServiceJabberImpl provider) { this.multiUserChat = multiUserChat; - + this.provider = provider; this.opSetMuc = (OperationSetMultiUserChatJabberImpl)provider .getOperationSet(OperationSetMultiUserChat.class); - + this.oldSubject = multiUserChat.getSubject(); - + multiUserChat.addSubjectUpdatedListener( new SmackSubjectUpdatedListener()); multiUserChat.addMessageListener(new SmackMessageListener()); multiUserChat.addParticipantStatusListener(new MemberListener()); + multiUserChat.addUserStatusListener(new UserListener()); } /** @@ -451,22 +460,29 @@ public void joinAs(String nickname, byte[] password) throws OperationFailedException { this.assertConnected(); - - this.nickname = nickname; - + + this.nickname = StringUtils.parseName(nickname); + try { multiUserChat.join(nickname, new String(password)); - + + ChatRoomMemberRole role = null; + + if(this.getUserRole() == null) + role = ChatRoomMemberRole.GUEST; + else + role = this.getUserRole(); + ChatRoomMemberJabberImpl member = new ChatRoomMemberJabberImpl( this, nickname, provider.getAccountID() .getAccountAddress(), - ChatRoomMemberRole.GUEST); + role); members.put(nickname, member); - + // We don't specify a reason. opSetMuc.fireLocalUserPresenceEvent(this, LocalUserChatRoomPresenceChangeEvent.LOCAL_USER_JOINED, null); @@ -474,7 +490,7 @@ public void joinAs(String nickname, byte[] password) catch (XMPPException ex) { String errorMessage; - + if(ex.getXMPPError().getCode() == 401) { errorMessage @@ -483,7 +499,7 @@ public void joinAs(String nickname, byte[] password) + " with nickname: " + nickname + ". The chat room requests a password."; - + logger.error(errorMessage, ex); throw new OperationFailedException( @@ -514,9 +530,9 @@ else if(ex.getXMPPError().getCode() == 407) + getName() + " with nickname: " + nickname; - + logger.error(errorMessage, ex); - + throw new OperationFailedException( errorMessage, OperationFailedException.GENERAL_ERROR, @@ -537,8 +553,8 @@ public void joinAs(String nickname) throws OperationFailedException { this.assertConnected(); - - this.nickname = nickname; + + this.nickname = StringUtils.parseName(nickname); try { @@ -552,12 +568,17 @@ public void joinAs(String nickname) if (members.get(nickname) == null) { + if(this.getUserRole() == null) + role = ChatRoomMemberRole.GUEST; + else + role = this.getUserRole(); + ChatRoomMemberJabberImpl member = new ChatRoomMemberJabberImpl( this, nickname, provider.getAccountID() .getAccountAddress(), - ChatRoomMemberRole.GUEST); + role); members.put(nickname, member); @@ -811,6 +832,27 @@ public ProtocolProviderService getParentProvider() return provider; } + /** + * Returns local user role in the context of this chatroom. + * + * @return ChatRoomMemberRole + */ + public ChatRoomMemberRole getUserRole() + { + return this.role; + } + + /** + * Sets the new rolefor the local user in the context of this chatroom. + * + * @param role the new role to be set for the local user + */ + public void setUserRole(ChatRoomMemberRole role) + { + fireLocalUserRoleEvent(getUserRole(), role); + this.role = role; + } + /** * Instances of this class should be registered as * ParticipantStatusListener in smack and translates events . @@ -1231,10 +1273,12 @@ public void removeMemberRoleListener(ChatRoomMemberRoleListener listener) /** * Returns the list of banned users. + * @return a list of all banned participants + * @throws OperationFailedException if we could not obtain the ban list */ public Iterator getBanList() throws OperationFailedException - { + { return banList.values().iterator(); } @@ -1258,13 +1302,13 @@ public void setUserNickname(String nickname) { logger.error("Failed to change nickname for chat room: " + getName()); - + throw new OperationFailedException("The " + nickname + "already exists in this chat room.", OperationFailedException.IDENTIFICATION_CONFLICT); - } + } } - + /** * Bans a user from the room. An admin or owner of the room can ban users * from a room. @@ -1278,7 +1322,7 @@ public void setUserNickname(String nickname) */ public void banParticipant(ChatRoomMember chatRoomMember, String reason) throws OperationFailedException - { + { try { multiUserChat.banUser(chatRoomMember.getContactAddress(), reason); @@ -1286,7 +1330,7 @@ public void banParticipant(ChatRoomMember chatRoomMember, String reason) catch (XMPPException e) { logger.error("Failed to ban participant.", e); - + // If a moderator or a user with an affiliation of "owner" or "admin" // was intended to be kicked. if (e.getXMPPError().getCode() == 405) @@ -1446,11 +1490,11 @@ private void fireMemberRoleEvent(ChatRoomMember member, = new ArrayList( memberRoleListeners); } - + for (ChatRoomMemberRoleListener listener : listeners) listener.memberRoleChanged(evt); } - + /** * Delivers the specified event to all registered message listeners. * @param evt the EventObject that we'd like delivered to all @@ -1482,7 +1526,7 @@ else if (evt instanceof ChatRoomMessageDeliveryFailedEvent) } } } - + /** * A listener that listens for packets of type Message and fires an event * to notifier interesting parties that a message was received. @@ -1564,14 +1608,17 @@ public void processPacket(Packet packet) fireMessageEvent(msgReceivedEvt); } } - + /** * A listener that is fired anytime a MUC room changes its subject. */ private class SmackSubjectUpdatedListener implements SubjectUpdatedListener { public void subjectUpdated(String subject, String from) - { + { + if (logger.isInfoEnabled()) + logger.info("Subject updated to " + subject); + ChatRoomPropertyChangeEvent evt = new ChatRoomPropertyChangeEvent( ChatRoomJabberImpl.this, @@ -1580,12 +1627,182 @@ public void subjectUpdated(String subject, String from) subject); firePropertyChangeEvent(evt); - + // Keeps track of the subject. oldSubject = subject; } } - + + /** + * A listener that is fired anytime your participant's status in a room + * is changed, such as the user being kicked, banned, or granted admin + * permissions. + */ + private class UserListener implements UserStatusListener + { + /** + * Called when a moderator kicked your user from the room. This + * means that you are no longer participanting in the room. + * + * @param actor the moderator that kicked your user from the room + * (e.g. user@host.org). + * @param reason the reason provided by the actor to kick you from + * the room. + */ + public void kicked(String actor, String reason) + { + opSetMuc.fireLocalUserPresenceEvent( + ChatRoomJabberImpl.this, + LocalUserChatRoomPresenceChangeEvent.LOCAL_USER_KICKED, + reason); + leave(); + } + + /** + * Called when a moderator grants voice to your user. This means that + * you were a visitor in the moderated room before and now you can + * participate in the room by sending messages to all occupants. + */ + public void voiceGranted() + { + setUserRole(ChatRoomMemberRole.MEMBER); + } + + /** + * Called when a moderator revokes voice from your user. This means that + * you were a participant in the room able to speak and now you are a + * visitor that can't send messages to the room occupants. + */ + public void voiceRevoked() + { + setUserRole(ChatRoomMemberRole.SILENT_MEMBER); + } + + /** + * Called when an administrator or owner banned your user from the room. + * This means that you will no longer be able to join the room unless the + * ban has been removed. + * + * @param actor the administrator that banned your user + * (e.g. user@host.org). + * @param reason the reason provided by the administrator to banned you. + */ + public void banned(String actor, String reason) + { + opSetMuc.fireLocalUserPresenceEvent(ChatRoomJabberImpl.this, + LocalUserChatRoomPresenceChangeEvent.LOCAL_USER_DROPPED, reason); + leave(); + } + + /** + * Called when an administrator grants your user membership to the room. + * This means that you will be able to join the members-only room. + */ + public void membershipGranted() + { + setUserRole(ChatRoomMemberRole.MEMBER); + } + + /** + * Called when an administrator revokes your user membership to the room. + * This means that you will not be able to join the members-only room. + */ + public void membershipRevoked() + { + setUserRole(ChatRoomMemberRole.GUEST); + } + + /** + * Called when an administrator grants moderator privileges to your user. + * This means that you will be able to kick users, grant and revoke + * voice, invite other users, modify room's subject plus all the + * participants privileges. + */ + public void moderatorGranted() + { + setUserRole(ChatRoomMemberRole.MODERATOR); + } + + /** + * Called when an administrator revokes moderator privileges from your + * user. This means that you will no longer be able to kick users, grant + * and revoke voice, invite other users, modify room's subject plus all + * the participants privileges. + */ + public void moderatorRevoked() + { + setUserRole(ChatRoomMemberRole.MEMBER); + } + + /** + * Called when an owner grants to your user ownership on the room. This + * means that you will be able to change defining room features as well + * as perform all administrative functions. + */ + public void ownershipGranted() + { + setUserRole(ChatRoomMemberRole.OWNER); + } + + /** + * Called when an owner revokes from your user ownership on the room. + * This means that you will no longer be able to change defining room + * features as well as perform all administrative functions. + */ + public void ownershipRevoked() + { + setUserRole(ChatRoomMemberRole.ADMINISTRATOR); + } + + /** + * Called when an owner grants administrator privileges to your user. + * This means that you will be able to perform administrative functions + * such as banning users and edit moderator list. + */ + public void adminGranted() + { + setUserRole(ChatRoomMemberRole.ADMINISTRATOR); + } + + /** + * Called when an owner revokes administrator privileges from your user. + * This means that you will no longer be able to perform administrative + * functions such as banning users and edit moderator list. + */ + public void adminRevoked() + { + setUserRole(ChatRoomMemberRole.MEMBER); + } + } + + /** + * Creates the corresponding ChatRoomLocalUserRoleChangeEvent and notifies + * all ChatRoomLocalUserRoleListeners that local user's role has + * been changed in this ChatRoom. + * + * @param previousRole the previous role that local user had + * @param newRole the new role the local user gets + */ + private void fireLocalUserRoleEvent(ChatRoomMemberRole previousRole, + ChatRoomMemberRole newRole) + { + ChatRoomLocalUserRoleChangeEvent evt + = new ChatRoomLocalUserRoleChangeEvent( + this, previousRole, newRole); + + logger.trace("Will dispatch the following ChatRoom event: " + evt); + + Iterable listeners; + synchronized (localUserRoleListeners) + { + listeners = new ArrayList( + localUserRoleListeners); + } + + for (ChatRoomLocalUserRoleListener listener : listeners) + listener.localUserRoleChanged(evt); + } + /** * Delivers the specified event to all registered property change listeners. * @@ -1731,8 +1948,8 @@ public boolean isPersistent() if (info != null) persistent = info.containsFeature("muc_persistent"); - - } catch (Exception ex) + } + catch (Exception ex) { logger.warn("could not get persistent state for room :" + roomName + "\n", ex); @@ -1750,4 +1967,247 @@ public ChatRoomMemberJabberImpl findMemberForNickName(String jabberID) { return (ChatRoomMemberJabberImpl) members.get(jabberID); } + + /** + * Grants administrator privileges to another user. Room owners may grant + * administrator privileges to a member or un-affiliated user. An + * administrator is allowed to perform administrative functions such as + * banning users and edit moderator list. + * + * @param jid the bare XMPP user ID of the user to grant administrator + * privileges (e.g. "user@host.org"). + * + * @throws XMPPException if an error occurs granting administrator privileges + * to a user. + */ + public void grantAdmin(String jid) + { + try + { + multiUserChat.grantAdmin(jid); + } + catch (XMPPException ex) + { + ex.printStackTrace(); + } + } + + /** + * Grants membership to a user. Only administrators are able to grant + * membership. A user that becomes a room member will be able to enter a room + * of type Members-Only (i.e. a room that a user cannot enter without being + * on the member list). + * + * @param jid the bare XMPP user ID of the user to grant membership + * privileges (e.g. "user@host.org"). + * + * @throws XMPPException if an error occurs granting membership to a user. + */ + public void grantMembership(String jid) + { + try + { + multiUserChat.grantMembership(jid); + } + catch (XMPPException ex) + { + ex.printStackTrace(); + } + } + + /** + * Grants moderator privileges to a participant or visitor. Room + * administrators may grant moderator privileges. A moderator is allowed to + * kick users, grant and revoke voice, invite other users, modify room's + * subject plus all the partcipants privileges. + * + * @param nickname the nickname of the occupant to grant moderator + * privileges. + * + * @throws XMPPException if an error occurs granting moderator privileges to + * a user. + */ + public void grantModerator(String nickname) + { + try + { + multiUserChat.grantModerator(nickname); + } + catch (XMPPException ex) + { + ex.printStackTrace(); + } + } + + /** + * Grants ownership privileges to another user. Room owners may grant + * ownership privileges. Some room implementations will not allow to grant + * ownership privileges to other users. An owner is allowed to change + * defining room features as well as perform all administrative functions. + * + * @param jid the bare XMPP user ID of the user to grant ownership + * privileges (e.g. "user@host.org"). + * + * @throws XMPPException if an error occurs granting ownership privileges to + * a user. + */ + public void grantOwnership(String jid) + { + try + { + multiUserChat.grantOwnership(jid); + } + catch (XMPPException ex) + { + ex.printStackTrace(); + } + } + + /** + * Grants voice to a visitor in the room. In a moderated room, a moderator + * may want to manage who does and does not have "voice" in the room. To have + * voice means that a room occupant is able to send messages to the room + * occupants. + * + * @param nickname the nickname of the visitor to grant voice in the room + * (e.g. "john"). + * + * @throws XMPPException if an error occurs granting voice to a visitor. In + * particular, a 403 error can occur if the occupant that intended to grant + * voice is not a moderator in this room (i.e. Forbidden error); or a 400 + * error can occur if the provided nickname is not present in the room. + */ + public void grantVoice(String nickname) + { + try + { + multiUserChat.grantVoice(nickname); + } + catch (XMPPException ex) + { + ex.printStackTrace(); + } + } + + /** + * Revokes administrator privileges from a user. The occupant that loses + * administrator privileges will become a member. Room owners may revoke + * administrator privileges from a member or unaffiliated user. + * + * @param jid the bare XMPP user ID of the user to grant administrator + * privileges (e.g. "user@host.org"). + * + * @throws XMPPException if an error occurs revoking administrator privileges + * to a user. + */ + public void revokeAdmin(String jid) + { + try + { + multiUserChat.revokeAdmin(jid); + } + catch (XMPPException ex) + { + ex.printStackTrace(); + } + } + + /** + * Revokes a user's membership. Only administrators are able to revoke + * membership. A user that becomes a room member will be able to enter a room + * of type Members-Only (i.e. a room that a user cannot enter without being + * on the member list). If the user is in the room and the room is of type + * members-only then the user will be removed from the room. + * + * @param jid the bare XMPP user ID of the user to revoke membership + * (e.g. "user@host.org"). + * + * @throws XMPPException if an error occurs revoking membership to a user. + */ + public void revokeMembership(String jid) + { + try + { + multiUserChat.revokeMembership(jid); + } + catch (XMPPException ex) + { + ex.printStackTrace(); + } + } + + /** + * Revokes moderator privileges from another user. The occupant that loses + * moderator privileges will become a participant. Room administrators may + * revoke moderator privileges only to occupants whose affiliation is member + * or none. This means that an administrator is not allowed to revoke + * moderator privileges from other room administrators or owners. + * + * @param nickname the nickname of the occupant to revoke moderator + * privileges. + * + * @throws XMPPException if an error occurs revoking moderator privileges + * from a user. + */ + public void revokeModerator(String nickname) + { + try + { + multiUserChat.revokeModerator(nickname); + } + catch (XMPPException ex) + { + ex.printStackTrace(); + } + } + + /** + * Revokes ownership privileges from another user. The occupant that loses + * ownership privileges will become an administrator. Room owners may revoke + * ownership privileges. Some room implementations will not allow to grant + * ownership privileges to other users. + * + * @param jid the bare XMPP user ID of the user to revoke ownership + * (e.g. "user@host.org"). + * + * @throws XMPPException if an error occurs revoking ownership privileges + * from a user. + */ + public void revokeOwnership(String jid) + { + try + { + multiUserChat.revokeOwnership(jid); + } + catch (XMPPException ex) + { + ex.printStackTrace(); + } + } + + /** + * Revokes voice from a participant in the room. In a moderated room, a + * moderator may want to revoke an occupant's privileges to speak. To have + * voice means that a room occupant is able to send messages to the room + * occupants. + * @param nickname the nickname of the participant to revoke voice + * (e.g. "john"). + * + * @throws XMPPException if an error occurs revoking voice from a + * participant. In particular, a 405 error can occur if a moderator or a user + * with an affiliation of "owner" or "admin" was tried to revoke his voice + * (i.e. Not Allowed error); or a 400 error can occur if the provided + * nickname is not present in the room. + */ + public void revokeVoice(String nickname) + { + try + { + multiUserChat.revokeVoice(nickname); + } + catch (XMPPException ex) + { + ex.printStackTrace(); + } + } } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomMemberJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomMemberJabberImpl.java index 8057fe8d2..1feb70fd6 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomMemberJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ChatRoomMemberJabberImpl.java @@ -22,10 +22,11 @@ public class ChatRoomMemberJabberImpl * The chat room that we are a member of. */ private final ChatRoomJabberImpl containingRoom; + /** * The role that this member has in its member room. */ - private final ChatRoomMemberRole role; + private ChatRoomMemberRole role; /** * The jabber id of the member (will only be visible to members with @@ -150,7 +151,16 @@ public ChatRoomMemberRole getRole() { return role; } - + + /** + * Sets the role of this member. + * @param role the role to set + */ + public void setRole(ChatRoomMemberRole role) + { + this.role = role; + } + /** * Returns the avatar of this member, that can be used when including it in * user interface. diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java index 7bc84fc34..5096dfa9b 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java @@ -14,6 +14,7 @@ import org.jivesoftware.smack.*; import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.util.*; import org.jivesoftware.smackx.*; import org.jivesoftware.smackx.muc.*; @@ -40,7 +41,8 @@ public class OperationSetMultiUserChatJabberImpl * we have not necessarily joined these rooms, we might have simply been * searching through them. */ - private final Hashtable chatRoomCache = new Hashtable(); + private final Hashtable chatRoomCache + = new Hashtable(); /** * The registration listener that would get notified when the underlying @@ -95,16 +97,21 @@ public ChatRoom createChatRoom( //first make sure we are connected and the server supports multichat assertSupportedAndConnected(); - ChatRoom room = findRoom(roomName); + ChatRoom room = null; + if (roomName == null) + roomName = "chatroom-" + StringUtils.randomString(4); + else + room = findRoom(roomName); if (room == null) { + logger.info("Find room returns null."); MultiUserChat muc = new MultiUserChat( getXmppConnection(), getCanonicalRoomName(roomName)); try { - muc.create(getXmppConnection().getUser()); + muc.create(StringUtils.parseName(getXmppConnection().getUser())); muc.sendConfigurationForm(new Form(Form.TYPE_SUBMIT)); } catch (XMPPException ex) @@ -115,7 +122,9 @@ public ChatRoom createChatRoom( , ex.getCause()); } room = createLocalChatRoomInstance(muc); + room.setUserRole(ChatRoomMemberRole.OWNER); } + room.join(); return room; } @@ -493,7 +502,12 @@ public ChatRoomJabberImpl getChatRoom(String chatRoomName) } /** - * Returns the list of currently joined chat rooms. + * Returns the list of currently joined chat rooms for + * chatRoomMember. + * @param chatRoomMember the member we're looking for + * @return a list of all currently joined chat rooms + * @throws OperationFailedException if the operation fails + * @throws OperationNotSupportedException if the operation is not supported */ public List getCurrentlyJoinedChatRooms(ChatRoomMember chatRoomMember) throws OperationFailedException, OperationNotSupportedException @@ -621,14 +635,14 @@ public void invitationDeclined(String invitee, String reason) } /** - * Our listener that will tell us when we're registered to jabber and the + * Our listener that will tell us when we're registered to Jabber and the * smack MultiUserChat is ready to accept us as a listener. */ private class RegistrationStateListener implements RegistrationStateChangeListener { /** - * The method is called by a ProtocolProvider implementation whenver + * The method is called by a ProtocolProvider implementation whenever * a change in the registration state of the corresponding provider had * occurred. * @param evt ProviderStatusChangeEvent the event describing the status @@ -650,6 +664,7 @@ public void registrationStateChanged(RegistrationStateChangeEvent evt) /** * Updates corresponding chat room members when a contact has been modified * in our contact list. + * @param evt the SubscriptionEvent that notified us */ public void contactModified(ContactPropertyChangeEvent evt) { @@ -661,6 +676,7 @@ public void contactModified(ContactPropertyChangeEvent evt) /** * Updates corresponding chat room members when a contact has been created * in our contact list. + * @param evt the SubscriptionEvent that notified us */ public void subscriptionCreated(SubscriptionEvent evt) { @@ -671,19 +687,20 @@ public void subscriptionCreated(SubscriptionEvent evt) /** * Not interested in this event for our member update purposes. + * @param evt the SubscriptionEvent that notified us */ - public void subscriptionFailed(SubscriptionEvent evt) - {} + public void subscriptionFailed(SubscriptionEvent evt) {} /** * Not interested in this event for our member update purposes. + * @param evt the SubscriptionEvent that notified us */ - public void subscriptionMoved(SubscriptionMovedEvent evt) - {} + public void subscriptionMoved(SubscriptionMovedEvent evt) {} /** * Updates corresponding chat room members when a contact has been removed * from our contact list. + * @param evt the SubscriptionEvent that notified us */ public void subscriptionRemoved(SubscriptionEvent evt) { @@ -694,9 +711,9 @@ public void subscriptionRemoved(SubscriptionEvent evt) /** * Not interested in this event for our member update purposes. + * @param evt the SubscriptionEvent that notified us */ - public void subscriptionResolved(SubscriptionEvent evt) - {} + public void subscriptionResolved(SubscriptionEvent evt) {} /** * Finds all chat room members, which name corresponds to the name of the diff --git a/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoom.java b/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoom.java index d387b1312..ceb4e7257 100644 --- a/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoom.java +++ b/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoom.java @@ -18,9 +18,9 @@ public class MockChatRoom implements ChatRoom { private MockProvider provider; - + private MockMultiUserChat parentOpSet = null; - + private String name; private String subject; @@ -36,19 +36,19 @@ public class MockChatRoom */ private final List memberPresenceListeners = new Vector(); - + /** * Currently registered local user role listeners. */ private final List localUserRoleListeners = new Vector(); - + /** * Currently registered member role listeners. */ private final List memberRoleListeners = new Vector(); - + /** * Currently registered property change listeners. */ @@ -60,11 +60,18 @@ public class MockChatRoom */ private final List messageListeners = new Vector(); - - public MockChatRoom( - MockProvider provider, - MockMultiUserChat parentOpSet, - String roomName) + + /** + * Creates an instance of MockChatRoom by specifying the + * corresponding protocol provider, the multi user chat operation set + * and the room name. + * @param provider the corresponding ProtocolProviderService + * @param parentOpSet the corresponding OperationSetMultiUserChat + * @param roomName the name of the room + */ + public MockChatRoom(MockProvider provider, + MockMultiUserChat parentOpSet, + String roomName) { this.provider = provider; this.name = roomName; @@ -546,35 +553,76 @@ public String getIdentifier() throw new UnsupportedOperationException("Not supported yet."); } + /** + * Bans a user from the room. Not implemented for mock chat rooms. + * + * @param chatRoomMember the ChatRoomMember to be banned + * @param reason the reason why the user was banned + * @throws OperationFailedException if an error occurs while banning a user + */ public void banParticipant(ChatRoomMember chatRoomMember, String reason) - throws OperationFailedException - { - } + throws OperationFailedException {} + /** + * Kicks a visitor or participant from the room. Not implemented for mock + * chat rooms. + * + * @param chatRoomMember the ChatRoomMember to kick from the room + * @param reason the reason why the participant is being kicked from the + * room + * @throws OperationFailedException if an error occurs while kicking the + * participant + */ public void kickParticipant(ChatRoomMember chatRoomMember, String reason) - throws OperationFailedException - { - } + throws OperationFailedException {} + /** + * Returns the ChatRoomConfigurationForm containing all + * configuration properties for this chat room. Not implemented for mock + * chat rooms. + * + * @return the ChatRoomConfigurationForm containing all + * configuration properties for this chat room + * @throws OperationFailedException if the user doesn't have + * permissions to see and change chat room configuration + */ public ChatRoomConfigurationForm getConfigurationForm() throws OperationFailedException { return null; } + /** + * Adds a listener that will be notified of changes in the property of a + * room member such as the nickname being changed. + * + * @param listener a room member property change listener. + */ public void addMemberPropertyChangeListener( ChatRoomMemberPropertyChangeListener listener) { // TODO Implement the addMemberPropertyChangeListener } + /** + * Removes a listener that was being notified of changes in the property of + * a chat room member such as the nickname being changed. + * + * @param listener a room member property change listener. + */ public void removeMemberPropertyChangeListener( ChatRoomMemberPropertyChangeListener listener) { // TODO Implement the removeMemberPropertyChangeListener - } - + + /** + * Returns true if this chat room is a system room and + * false otherwise. + * + * @return true if this chat room is a system room and + * false otherwise. + */ public boolean isSystem() { return false; @@ -592,4 +640,117 @@ public boolean isPersistent() { return true; } + + /** + * Grants admin role to the participant given by address. + * @param address the address of the participant to grant admin role to + */ + public void grantAdmin(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Grants membership role to the participant given by address. + * @param address the address of the participant to grant membership role to + */ + public void grantMembership(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Grants moderator role to the participant given by address. + * @param address the address of the participant to grant moderator role to + */ + public void grantModerator(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Grants ownership role to the participant given by address. + * @param address the address of the participant to grant ownership role to + */ + public void grantOwnership(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Grants voice to the participant given by address. + * @param address the address of the participant to grant voice to + */ + public void grantVoice(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Revokes the admin role for the participant given by address. + * @param address the address of the participant to revoke admin role for + */ + public void revokeAdmin(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Revokes the membership role for the participant given by address. + * @param address the address of the participant to revoke membership role + * for + */ + public void revokeMembership(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Revokes the moderator role for the participant given by address. + * @param address the address of the participant to revoke moderator role + * for + */ + public void revokeModerator(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Revokes the ownership role for the participant given by address. + * @param address the address of the participant to revoke ownership role + * for + */ + public void revokeOwnership(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Revokes the voice for the participant given by address. + * @param address the address of the participant to revoke voice for + */ + public void revokeVoice(String address) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Returns the local user role. + * @return the local user role + */ + public ChatRoomMemberRole getUserRole() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /** + * Sets the local user role. + * @param role the role to set + * @throws OperationFailedException if the operation don't succeed + */ + public void setUserRole(ChatRoomMemberRole role) + throws OperationFailedException + { + throw new UnsupportedOperationException("Not supported yet."); + } } diff --git a/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoomMember.java b/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoomMember.java index 8860145cd..ef0b98572 100644 --- a/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoomMember.java +++ b/src/net/java/sip/communicator/impl/protocol/mock/MockChatRoomMember.java @@ -21,6 +21,18 @@ public class MockChatRoomMember private Contact contact; private byte[] avatar; + /** + * Creates an instance of MockChatRoomMember by specifying the + * name of the member, the chatRoom, to which it belongs, + * its role in the room, the contact corresponding to it + * and its avatar. + * @param name the name of the member + * @param chatRoom the chat room to which the member belongs + * @param role the role of the member in the room + * @param contact the contact corresponding to this member in the local + * contact list + * @param avatar the avatar of the member + */ public MockChatRoomMember(String name, ChatRoom chatRoom, ChatRoomMemberRole role, Contact contact, byte[] avatar) { @@ -92,6 +104,15 @@ public ChatRoomMemberRole getRole() return role; } + /** + * Sets the role of this member. + * @param role the role to set + */ + public void setRole(ChatRoomMemberRole role) + { + throw new UnsupportedOperationException("Not supported yet."); + } + /** * Returns the avatar of this member, that can be used when including it in * user interface. diff --git a/src/net/java/sip/communicator/service/protocol/ChatRoom.java b/src/net/java/sip/communicator/service/protocol/ChatRoom.java index 027508db6..587618651 100644 --- a/src/net/java/sip/communicator/service/protocol/ChatRoom.java +++ b/src/net/java/sip/communicator/service/protocol/ChatRoom.java @@ -16,6 +16,7 @@ * * @author Emil Ivov * @author Yana Stamcheva + * @author Valentin Martinet */ public interface ChatRoom { @@ -141,6 +142,25 @@ public void setSubject(String subject) */ public String getUserNickname(); + /** + * Returns the local user's role in the context of this chat room or + * null if not currently joined. + * + * @return the role currently being used by the local user in the context of + * the chat room. + */ + public ChatRoomMemberRole getUserRole(); + + /** + * Changes the the local user's nickname in the context of this chatroom. + * + * @param role the new role to set for the local user. + * + * @throws OperationFailedException if an error occurs. + */ + public void setUserRole(ChatRoomMemberRole role) + throws OperationFailedException; + /** * Changes the the local user's nickname in the context of this chatroom. * @@ -261,14 +281,12 @@ public void removeMemberPropertyChangeListener( * * @return a List of ChatRoomMember instances * corresponding to all room members. - * @throws OperationFailedException if we fail retrieving the list of room - * participants. */ public List getMembers(); /** * Returns the number of participants that are currently in this chat room. - * @return int the number of Contacts, currently participating in + * @return the number of Contacts, currently participating in * this room. */ public int getMembersCount(); @@ -339,7 +357,7 @@ public void sendMessage(Message message) */ public Iterator getBanList() throws OperationFailedException; - + /** * Bans a user from the room. An administrator or owner of the room can ban * users from a room. A banned user will no longer be able to join the room @@ -357,7 +375,7 @@ public Iterator getBanList() */ public void banParticipant(ChatRoomMember chatRoomMember, String reason) throws OperationFailedException; - + /** * Kicks a visitor or participant from the room. * @@ -372,7 +390,7 @@ public void banParticipant(ChatRoomMember chatRoomMember, String reason) */ public void kickParticipant(ChatRoomMember chatRoomMember, String reason) throws OperationFailedException; - + /** * Returns the ChatRoomConfigurationForm containing all * configuration properties for this chat room. If the user doesn't have @@ -405,4 +423,114 @@ public ChatRoomConfigurationForm getConfigurationForm() * @return true if this chat room is persistent, false otherwise */ public boolean isPersistent(); + + /** + * Grants administrator privileges to another user. Room owners may grant + * administrator privileges to a member or unaffiliated user. An + * administrator is allowed to perform administrative functions such as + * banning users and edit moderator list. + * + * @param address the user address of the user to grant administrator + * privileges (e.g. "user@host.org"). + */ + public void grantAdmin(String address); + + /** + * Grants membership to a user. Only administrators are able to grant + * membership. A user that becomes a room member will be able to enter a room + * of type Members-Only (i.e. a room that a user cannot enter without being + * on the member list). + * + * @param address the user address of the user to grant membership + * privileges (e.g. "user@host.org"). + */ + public void grantMembership(String address); + + /** + * Grants moderator privileges to a participant or visitor. Room + * administrators may grant moderator privileges. A moderator is allowed to + * kick users, grant and revoke voice, invite other users, modify room's + * subject plus all the partcipants privileges. + * + * @param nickname the nickname of the occupant to grant moderator + * privileges. + */ + public void grantModerator(String nickname); + + /** + * Grants ownership privileges to another user. Room owners may grant + * ownership privileges. Some room implementations will not allow to grant + * ownership privileges to other users. An owner is allowed to change + * defining room features as well as perform all administrative functions. + * + * @param address the user address of the user to grant ownership + * privileges (e.g. "user@host.org"). + */ + public void grantOwnership(String address); + + /** + * Grants voice to a visitor in the room. In a moderated room, a moderator + * may want to manage who does and does not have "voice" in the room. To have + * voice means that a room occupant is able to send messages to the room + * occupants. + * + * @param nickname the nickname of the visitor to grant voice in the room + * (e.g. "john"). + */ + public void grantVoice(String nickname); + + /** + * Revokes administrator privileges from a user. The occupant that loses + * administrator privileges will become a member. Room owners may revoke + * administrator privileges from a member or unaffiliated user. + * + * @param address the user address of the user to grant administrator + * privileges (e.g. "user@host.org"). + */ + public void revokeAdmin(String address); + + /** + * Revokes a user's membership. Only administrators are able to revoke + * membership. A user that becomes a room member will be able to enter a room + * of type Members-Only (i.e. a room that a user cannot enter without being + * on the member list). If the user is in the room and the room is of type + * members-only then the user will be removed from the room. ÊÊ + * + * @param address the user address of the user to revoke membership + * (e.g. "user@host.org"). + */ + public void revokeMembership(String address); + + /** + * Revokes moderator privileges from another user. The occupant that loses + * moderator privileges will become a participant. Room administrators may + * revoke moderator privileges only to occupants whose affiliation is member + * or none. This means that an administrator is not allowed to revoke + * moderator privileges from other room administrators or owners. + * + * @param nickname the nickname of the occupant to revoke moderator + * privileges. + */ + public void revokeModerator(String nickname); + + /** + * Revokes ownership privileges from another user. The occupant that loses + * ownership privileges will become an administrator. Room owners may revoke + * ownership privileges. Some room implementations will not allow to grant + * ownership privileges to other users. Ê + * + * @param address the user address of the user to revoke ownership + * (e.g. "user@host.org"). + */ + public void revokeOwnership(String address); + + /** + * Revokes voice from a participant in the room. In a moderated room, a + * moderator may want to revoke an occupant's privileges to speak. To have + * voice means that a room occupant is able to send messages to the room + * occupants. + * @param nickname the nickname of the participant to revoke voice + * (e.g. "john"). + */ + public void revokeVoice(String nickname); } diff --git a/src/net/java/sip/communicator/service/protocol/ChatRoomMember.java b/src/net/java/sip/communicator/service/protocol/ChatRoomMember.java index 10a8a4f49..a42f52f5e 100644 --- a/src/net/java/sip/communicator/service/protocol/ChatRoomMember.java +++ b/src/net/java/sip/communicator/service/protocol/ChatRoomMember.java @@ -80,4 +80,12 @@ public interface ChatRoomMember * the this member in its containing chat room. */ public ChatRoomMemberRole getRole(); + + /** + * Sets the role of this chat room member in its containing room. + * + * @param role ChatRoomMemberRole instance indicating the role + * to set for this member in its containing chat room. + */ + public void setRole(ChatRoomMemberRole role); } diff --git a/src/net/java/sip/communicator/service/protocol/ChatRoomMemberRole.java b/src/net/java/sip/communicator/service/protocol/ChatRoomMemberRole.java index 95d7b8cad..5d144e20d 100644 --- a/src/net/java/sip/communicator/service/protocol/ChatRoomMemberRole.java +++ b/src/net/java/sip/communicator/service/protocol/ChatRoomMemberRole.java @@ -10,53 +10,47 @@ * Indicates roles that a chat room member detains in its containing chat room. * * @author Emil Ivov + * @author Valentin Martinet + * @author Yana Stamcheva */ -public class ChatRoomMemberRole +public enum ChatRoomMemberRole implements Comparable { /** * A role implying the full set of chat room permissions */ - public static final ChatRoomMemberRole OWNER - = new ChatRoomMemberRole("Owner", 70); + OWNER("Owner", 70), /** * A role implying administrative permissions. */ - public static final ChatRoomMemberRole ADMINISTRATOR - = new ChatRoomMemberRole("Administrator", 60); + ADMINISTRATOR("Administrator", 60), /** * A role implying moderator permissions. */ - public static final ChatRoomMemberRole MODERATOR - = new ChatRoomMemberRole("Moderator", 50); + MODERATOR("Moderator", 50), /** * A role implying standard participant permissions. */ - public static final ChatRoomMemberRole MEMBER - = new ChatRoomMemberRole("Member", 40); + MEMBER("Member", 40), /** * A role implying standard participant permissions. */ - public static final ChatRoomMemberRole GUEST - = new ChatRoomMemberRole("Guest", 30); - + GUEST("Guest", 30), /** * A role implying standard participant permissions without the right to * send messages/speak. */ - public static final ChatRoomMemberRole SILENT_MEMBER - = new ChatRoomMemberRole("SilentMember", 30); + SILENT_MEMBER("SilentMember", 20), /** * A role implying an explicit ban for the user to join the room. */ - public static final ChatRoomMemberRole OUTCAST - = new ChatRoomMemberRole("Outcast", 20); + OUTCAST("Outcast", 10); /** * the name of this role. @@ -83,7 +77,7 @@ public class ChatRoomMemberRole * * @throws java.lang.NullPointerException if roleName is null. */ - protected ChatRoomMemberRole(String roleName, int roleIndex) + private ChatRoomMemberRole(String roleName, int roleIndex) throws NullPointerException { if(roleName == null) @@ -126,61 +120,4 @@ public int getRoleIndex() { return roleIndex; } - - /** - * Indicates whether some other object is "equal to" this role instance. - *

- * @param obj the reference object with which to compare. - * @return true if obj is a role instance that has the same - * name and role index as this one. - */ - public boolean equals(Object obj) - { - if (obj == this) - return true; - - /* - * XXX Implementing Object#equals(Object) with instanceof is error - * prone. The safe and recommended approach is to return true only if - * the runtime types of the two Objects being tested are one and the - * same i.e. getClass().equals(obj.getClass()). - */ - if (!(obj instanceof ChatRoomMemberRole)) - return false; - - ChatRoomMemberRole role = (ChatRoomMemberRole) obj; - - return role.getRoleName().equals(getRoleName()) - && (role.getRoleIndex() == getRoleIndex()); - } - - /** - * Returns a hash code value for the object. This method is - * supported for the benefit of hashtables such as those provided by - * java.util.Hashtable. - *

- * @return a hash code value for this object. - */ - public int hashCode() - { - return getRoleName().hashCode(); - } - - /** - * Compares this role's role index with that of the specified object for - * order. Returns a negative integer, zero, or a positive integer as this - * role is less than, equal to, or greater than the specified object. - * - * @param obj the object to be compared. - * @return a negative integer, zero, or a positive integer as this object - * is less than, equal to, or greater than the specified object. - * - * @throws ClassCastException if the specified object's type is not an - * instance of ChatRoomMemberRole. - */ - public int compareTo(ChatRoomMemberRole obj) - throws ClassCastException - { - return getRoleIndex() - obj.getRoleIndex(); - } }