/** * $RCSfile: ,v $ * $Revision: $ * $Date: $ * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jivesoftware.spark.ui.conferences; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.DefaultListModel; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.ListCellRenderer; import javax.swing.SwingUtilities; import org.jdesktop.swingx.JXList; import org.jivesoftware.resource.Res; import org.jivesoftware.resource.SparkRes; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.XMPPError; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.ServiceDiscoveryManager; import org.jivesoftware.smackx.muc.Affiliate; import org.jivesoftware.smackx.muc.InvitationRejectionListener; import org.jivesoftware.smackx.muc.MultiUserChat; import org.jivesoftware.smackx.muc.Occupant; import org.jivesoftware.smackx.muc.UserStatusListener; import org.jivesoftware.smackx.packet.DiscoverInfo; import org.jivesoftware.spark.ChatManager; import org.jivesoftware.spark.PresenceManager; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.UserManager; import org.jivesoftware.spark.component.ImageTitlePanel; import org.jivesoftware.spark.ui.ChatRoom; import org.jivesoftware.spark.ui.ChatRoomListener; import org.jivesoftware.spark.ui.ChatRoomNotFoundException; import org.jivesoftware.spark.ui.rooms.ChatRoomImpl; import org.jivesoftware.spark.ui.rooms.GroupChatRoom; import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.log.Log; import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; import org.jivesoftware.sparkimpl.settings.local.SettingsManager; /** * The <code>RoomInfo</code> class is used to display all room information, such * as agents and room information. */ public class GroupChatParticipantList extends JPanel implements ChatRoomListener { private static final long serialVersionUID = 3809155443119207342L; private GroupChatRoom groupChatRoom; private final ImageTitlePanel agentInfoPanel; private ChatManager chatManager; private MultiUserChat chat; private LocalPreferences _localPreferences = SettingsManager.getLocalPreferences(); private final Map<String, String> userMap = new HashMap<String, String>(); private UserManager userManager = SparkManager.getUserManager(); private DefaultListModel model = new DefaultListModel(); private JXList participantsList; private PacketListener listener = null; private Map<String, String> invitees = new HashMap<String, String>(); private boolean allowNicknameChange = true; private DiscoverInfo roomInformation; private List<JLabel> users = new ArrayList<JLabel>(); private HashMap<String,String> usersandRoles = new HashMap<String,String>(); /** * Creates a new RoomInfo instance using the specified ChatRoom. The * RoomInfo component is responsible for monitoring all activity in the * ChatRoom. */ public GroupChatParticipantList() { setLayout(new GridBagLayout()); chatManager = SparkManager.getChatManager(); agentInfoPanel = new ImageTitlePanel(Res .getString("message.participants.in.room")); participantsList = new JXList(model); participantsList.setCellRenderer(new ParticipantRenderer()); // Set the room to track this.setOpaque(false); this.setBackground(Color.white); // Respond to Double-Click in Agent List to start a chat participantsList.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent evt) { if (evt.getClickCount() == 2) { String selectedUser = getSelectedUser(); startChat(groupChatRoom, userMap.get(selectedUser)); } } public void mouseReleased(final MouseEvent evt) { if (evt.isPopupTrigger()) { checkPopup(evt); } } public void mousePressed(final MouseEvent evt) { if (evt.isPopupTrigger()) { checkPopup(evt); } } }); JScrollPane scroller = new JScrollPane(participantsList); // Speed up scrolling. It was way too slow. scroller.getVerticalScrollBar().setBlockIncrement(200); scroller.getVerticalScrollBar().setUnitIncrement(20); scroller.setBackground(Color.white); scroller.getViewport().setBackground(Color.white); add(scroller, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets( 0, 0, 0, 0), 0, 0)); } public void setChatRoom(final ChatRoom chatRoom) { this.groupChatRoom = (GroupChatRoom) chatRoom; chatManager.addChatRoomListener(this); chat = groupChatRoom.getMultiUserChat(); chat.addInvitationRejectionListener(new InvitationRejectionListener() { public void invitationDeclined(String jid, String message) { String nickname = userManager.getUserNicknameFromJID(jid); userHasLeft(chatRoom, nickname); chatRoom.getTranscriptWindow().insertNotificationMessage( nickname + " has rejected the invitation.", ChatManager.NOTIFICATION_COLOR); } }); listener = new PacketListener() { public void processPacket(final Packet packet) { SwingUtilities.invokeLater(new Runnable() { public void run() { Presence p = (Presence) packet; if (p.getError() != null) { if (p.getError() .getCondition() .equals(XMPPError.Condition.conflict .toString())) { return; } } final String userid = p.getFrom(); String displayName = StringUtils.parseResource(userid); userMap.put(displayName, userid); if (p.getType() == Presence.Type.available) { String jid = PresenceManager.getJidFromMUCPresence(p); addParticipant(userid, p, jid); agentInfoPanel.setVisible(true); } else { removeUser(displayName); } } }); } }; chat.addParticipantListener(listener); ServiceDiscoveryManager disco = ServiceDiscoveryManager .getInstanceFor(SparkManager.getConnection()); try { roomInformation = disco.discoverInfo(chat.getRoom()); } catch (XMPPException e) { Log.debug("Unable to retrieve room information for " + chat.getRoom()); } } public void chatRoomOpened(ChatRoom room) { if (room != groupChatRoom) { return; } chat.addUserStatusListener(new UserStatusListener() { public void kicked(String actor, String reason) { } public void voiceGranted() { } public void voiceRevoked() { } public void banned(String actor, String reason) { } public void membershipGranted() { } public void membershipRevoked() { } public void moderatorGranted() { } public void moderatorRevoked() { } public void ownershipGranted() { } public void ownershipRevoked() { } public void adminGranted() { } public void adminRevoked() { } }); } public void chatRoomLeft(ChatRoom room) { if (this.groupChatRoom == room) { chatManager.removeChatRoomListener(this); agentInfoPanel.setVisible(false); } } public void chatRoomClosed(ChatRoom room) { if (this.groupChatRoom == room) { chatManager.removeChatRoomListener(this); chat.removeParticipantListener(listener); } } public void chatRoomActivated(ChatRoom room) { } public void userHasJoined(ChatRoom room, String userid) { } public void addInvitee(String jid, String message) { // So the problem with this is that I have no idea what the users actual // jid is in most cases. final UserManager userManager = SparkManager.getUserManager(); String displayName = userManager.getUserNicknameFromJID(jid); groupChatRoom.getTranscriptWindow().insertNotificationMessage( displayName + " has been invited to join this room.", ChatManager.NOTIFICATION_COLOR); if (roomInformation != null && !roomInformation.containsFeature("muc_nonanonymous")) { return; } final ImageIcon inviteIcon = SparkRes .getImageIcon(SparkRes.USER1_BACK_16x16); addUser(inviteIcon, displayName); invitees.put(displayName, message); } protected ImageIcon getImageIcon(String participantJID) { String displayName = StringUtils.parseResource(participantJID); ImageIcon icon = SparkRes.getImageIcon(SparkRes.GREEN_BALL); icon.setDescription(displayName); return icon; } protected void addParticipant(final String participantJID, Presence presence, String userJID) { // Remove reference to invitees for (String displayName : invitees.keySet()) { String jid = SparkManager.getUserManager().getJIDFromDisplayName( displayName); Occupant occ = chat.getOccupant(participantJID); if (occ != null) { String actualJID = occ.getJid(); if (actualJID.equals(jid)) { removeUser(displayName); } } } String nickname = StringUtils.parseResource(participantJID); String affiliation = parseRoleFromPacket(presence)[0]; String userRole = parseRoleFromPacket(presence)[1]; usersandRoles.put(participantJID, affiliation+","+userRole); Icon icon = null; if (_localPreferences.isShowingRoleIcons()) { icon = getIconForRole(userRole, affiliation); } else { Presence jidPresence = PresenceManager.getPresence(userJID); icon = PresenceManager.getIconFromPresence(jidPresence); if (icon == null) { icon = SparkRes.getImageIcon(SparkRes.GREEN_BALL); } } if (!exists(nickname)) { addUser(icon, nickname); } else { int index = getIndex(nickname); if (index != -1) { final JLabel userLabel = new JLabel(nickname, icon, JLabel.HORIZONTAL); model.setElementAt(userLabel, index); } } } /** * Parses the Affiliation and Role from the Presence packet * @param p * @return String[] ,[0]=affiliation , [1]=role */ protected String[] parseRoleFromPacket(Presence p) { String affi = ""; String role = ""; for (PacketExtension pack : p.getExtensions()) { String[] args = pack.toXML().split(" "); for (String ss : args) { int first = ss.indexOf("\""); int last = ss.lastIndexOf("\""); if (ss.contains("affiliation")) { if (first >=0 && first < last) { affi = ss.substring(first + 1, last); } } if (ss.contains("role")) { if (first >=0 && first < last) { role = ss.substring(first + 1, last); } } } } if (affi.equals("")) affi = "none"; if (role.equals("")) role = "participant"; return new String[] { affi, role }; } /** * Returns corresponding Icons for each MUC-Role * icons are: <br> * Owner = Gold Star <br> * Admin = Silver Star <br> * Moderator = Bronze Star <br> * Member = Yellow <br> * Participant = Green <br> * Visitor = Blue <br> * N/A = Grey <br> * @param role * @return {@link Icon} */ private Icon getIconForRole(String role, String affiliation) { Icon icon = null; if (role.equalsIgnoreCase("participant")) { icon = SparkRes.getImageIcon(SparkRes.STAR_GREEN_IMAGE); } else if (role.equalsIgnoreCase("moderator")) { icon = SparkRes.getImageIcon(SparkRes.STAR_MODERATOR); } else if (role.equalsIgnoreCase("visitor")) { icon = SparkRes.getImageIcon(SparkRes.STAR_BLUE_IMAGE); } else { icon = SparkRes.getImageIcon(SparkRes.STAR_GREY_IMAGE); } if (affiliation.equalsIgnoreCase("owner")) { icon = SparkRes.getImageIcon(SparkRes.STAR_OWNER); } if (affiliation.equalsIgnoreCase("admin")) { icon = SparkRes.getImageIcon(SparkRes.STAR_ADMIN); } if (affiliation.equalsIgnoreCase("member")) { if (role.equals("moderator")) { icon = SparkRes.getImageIcon(SparkRes.STAR_MODERATOR); } else { icon = SparkRes.getImageIcon(SparkRes.STAR_YELLOW_IMAGE); } } return icon; } public void userHasLeft(ChatRoom room, String userid) { if (room != groupChatRoom) { return; } int index = getIndex(userid); if (index != -1) { removeUser(userid); userMap.remove(userid); } } protected boolean exists(String nickname) { for (int i = 0; i < model.getSize(); i++) { final JLabel userLabel = (JLabel) model.getElementAt(i); if (userLabel.getText().equals(nickname)) { return true; } } return false; } protected String getSelectedUser() { JLabel label = (JLabel) participantsList.getSelectedValue(); if (label != null) { return label.getText(); } return null; } protected void startChat(ChatRoom groupChat, String groupJID) { String userNickname = StringUtils.parseResource(groupJID); String roomTitle = userNickname + " - " + StringUtils.parseName(groupChat.getRoomname()); String nicknameOfUser = StringUtils.parseResource(groupJID); String nickname = groupChat.getNickname(); if (nicknameOfUser.equals(nickname)) { return; } ChatRoom chatRoom; try { chatRoom = chatManager.getChatContainer().getChatRoom(groupJID); } catch (ChatRoomNotFoundException e) { Log.debug("Could not find chat room - " + groupJID); // Create new room chatRoom = new ChatRoomImpl(groupJID, nicknameOfUser, roomTitle); chatManager.getChatContainer().addChatRoom(chatRoom); } chatManager.getChatContainer().activateChatRoom(chatRoom); } public void tabSelected() { // To change body of implemented methods use File | Settings | File // Templates. } public String getTabTitle() { return Res.getString("title.room.information"); } public Icon getTabIcon() { return SparkRes.getImageIcon(SparkRes.SMALL_BUSINESS_MAN_VIEW); } public String getTabToolTip() { return Res.getString("title.room.information"); } public JComponent getGUI() { return this; } protected void kickUser(String nickname) { try { chat.kickParticipant(nickname, Res .getString("message.you.have.been.kicked")); } catch (XMPPException e) { groupChatRoom.insertText(Res.getString("message.kicked.error", nickname)); } } protected void banUser(String displayName) { try { Occupant occupant = chat.getOccupant(userMap.get(displayName)); if (occupant != null) { String bareJID = StringUtils .parseBareAddress(occupant.getJid()); chat.banUser(bareJID, Res .getString("message.you.have.been.banned")); } } catch (XMPPException e) { groupChatRoom.getTranscriptWindow(). insertNotificationMessage("No can do "+e.getMessage(), ChatManager.ERROR_COLOR); } } protected void unbanUser(String jid) { try { chat.grantMembership(jid); } catch (XMPPException e) { groupChatRoom.getTranscriptWindow(). insertNotificationMessage("No can do "+e.getMessage(), ChatManager.ERROR_COLOR); } } protected void grantVoice(String nickname) { try { chat.grantVoice(nickname); } catch (XMPPException e) { groupChatRoom.getTranscriptWindow(). insertNotificationMessage("No can do "+e.getMessage(), ChatManager.ERROR_COLOR); } } protected void revokeVoice(String nickname) { try { chat.revokeVoice(nickname); } catch (XMPPException e) { groupChatRoom.getTranscriptWindow(). insertNotificationMessage("No can do "+e.getMessage(), ChatManager.ERROR_COLOR); } } protected void grantModerator(String nickname) { try { chat.grantModerator(nickname); } catch (XMPPException e) { groupChatRoom.getTranscriptWindow().insertNotificationMessage( "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); } } protected void revokeModerator(String nickname) { try { chat.revokeModerator(nickname); } catch (XMPPException e) { groupChatRoom.getTranscriptWindow().insertNotificationMessage( "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); } } protected void grantMember(String nickname) { try { Occupant o = userManager.getOccupant(groupChatRoom,nickname); nickname = StringUtils.parseBareAddress(o.getJid()); chat.grantMembership(nickname); } catch (XMPPException e) { groupChatRoom.getTranscriptWindow().insertNotificationMessage( "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); } } protected void revokeMember(String nickname) { try { Occupant o = userManager.getOccupant(groupChatRoom,nickname); nickname = StringUtils.parseBareAddress(o.getJid()); chat.revokeMembership(nickname); } catch (XMPPException e) { groupChatRoom.getTranscriptWindow().insertNotificationMessage( "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); } } protected void grantAdmin(String nickname) { try { Occupant o = userManager.getOccupant(groupChatRoom,nickname); nickname = StringUtils.parseBareAddress(o.getJid()); chat.grantAdmin(nickname); } catch (XMPPException e) { groupChatRoom.getTranscriptWindow().insertNotificationMessage( "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); } } protected void revokeAdmin(String nickname) { try { Occupant o = userManager.getOccupant(groupChatRoom,nickname); nickname = StringUtils.parseBareAddress(o.getJid()); chat.revokeAdmin(nickname); } catch (XMPPException e) { groupChatRoom.getTranscriptWindow().insertNotificationMessage( "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); } } protected void grantOwner(String nickname) { try { Occupant o = userManager.getOccupant(groupChatRoom,nickname); nickname = StringUtils.parseBareAddress(o.getJid()); chat.grantOwnership(nickname); } catch (XMPPException e) { groupChatRoom.getTranscriptWindow().insertNotificationMessage( "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); } } protected void revokeOwner(String nickname) { try { Occupant o = userManager.getOccupant(groupChatRoom,nickname); nickname = StringUtils.parseBareAddress(o.getJid()); chat.revokeOwnership(nickname); } catch (XMPPException e) { groupChatRoom.getTranscriptWindow().insertNotificationMessage( "No can do " + e.getMessage(), ChatManager.ERROR_COLOR); } } /** * Let's make sure that the panel doesn't strech past the scrollpane view * pane. * * @return the preferred dimension */ public Dimension getPreferredSize() { final Dimension size = super.getPreferredSize(); size.width = 150; return size; } protected void checkPopup(MouseEvent evt) { Point p = evt.getPoint(); final int index = participantsList.locationToIndex(p); final JPopupMenu popup = new JPopupMenu(); if (index != -1) { participantsList.setSelectedIndex(index); final JLabel userLabel = (JLabel) model.getElementAt(index); final String selectedUser = userLabel.getText(); final String groupJID = userMap.get(selectedUser); String groupJIDNickname = StringUtils.parseResource(groupJID); final String nickname = groupChatRoom.getNickname(); final Occupant occupant = userManager.getOccupant(groupChatRoom, selectedUser); final boolean iamAdmin = SparkManager.getUserManager().isAdmin( groupChatRoom, chat.getNickname()); final boolean iamOwner = SparkManager.getUserManager().isOwner(groupChatRoom, chat.getNickname()); final boolean iamAdminOrOwner = iamAdmin || iamOwner; final boolean iamModerator = SparkManager.getUserManager() .isModerator(groupChatRoom, chat.getNickname()); final boolean userIsMember = SparkManager.getUserManager().isMember(occupant); final boolean userIsAdmin = userManager.isAdmin(groupChatRoom, occupant.getNick()); final boolean userIsOwner = userManager.isOwner(occupant); final boolean userIsModerator = userManager.isModerator(occupant); boolean selectedMyself = nickname.equals(groupJIDNickname); // Handle invites if (groupJIDNickname == null) { Action inviteAgainAction = new AbstractAction() { private static final long serialVersionUID = -1875073139356098243L; public void actionPerformed(ActionEvent actionEvent) { String message = invitees.get(selectedUser); String jid = userManager .getJIDFromDisplayName(selectedUser); chat.invite(jid, message); } }; inviteAgainAction.putValue(Action.NAME, Res.getString("menuitem.inivite.again")); popup.add(inviteAgainAction); Action removeInvite = new AbstractAction() { private static final long serialVersionUID = -3647279452501661970L; public void actionPerformed(ActionEvent actionEvent) { int index = getIndex(selectedUser); if (index != -1) { model.removeElementAt(index); } } }; removeInvite.putValue(Action.NAME, Res.getString("menuitem.remove")); popup.add(removeInvite); popup.show(participantsList, evt.getX(), evt.getY()); return; } if (selectedMyself) { Action changeNicknameAction = new AbstractAction() { private static final long serialVersionUID = -7891803180672794112L; public void actionPerformed(ActionEvent actionEvent) { String newNickname = JOptionPane.showInputDialog( groupChatRoom, Res.getString("label.new.nickname") + ":", Res.getString("title.change.nickname"), JOptionPane.QUESTION_MESSAGE); if (ModelUtil.hasLength(newNickname)) { while (true) { newNickname = newNickname.trim(); String nick = chat.getNickname(); if (newNickname.equals(nick)) { // return; } try { chat.changeNickname(newNickname); break; } catch (XMPPException e1) { if (e1.getXMPPError().getCode() == 406) { // handle // deny // changing // nick JOptionPane .showMessageDialog( groupChatRoom, Res.getString("message.nickname.not.acceptable"), Res.getString("title.change.nickname"), JOptionPane.ERROR_MESSAGE); break; } newNickname = JOptionPane .showInputDialog( groupChatRoom, Res.getString("message.nickname.in.use") + ":", Res.getString("title.change.nickname"), JOptionPane.QUESTION_MESSAGE); if (!ModelUtil.hasLength(newNickname)) { break; } } } } } }; changeNicknameAction.putValue(Action.NAME, Res.getString("menuitem.change.nickname")); changeNicknameAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.DESKTOP_IMAGE)); if (allowNicknameChange) { popup.add(changeNicknameAction); } } Action chatAction = new AbstractAction() { private static final long serialVersionUID = -2739549054781928195L; public void actionPerformed(ActionEvent actionEvent) { String selectedUser = getSelectedUser(); startChat(groupChatRoom, userMap.get(selectedUser)); } }; chatAction.putValue(Action.NAME, Res.getString("menuitem.start.a.chat")); chatAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_MESSAGE_IMAGE)); if (!selectedMyself) { popup.add(chatAction); } Action blockAction = new AbstractAction() { private static final long serialVersionUID = 8771362206105723776L; public void actionPerformed(ActionEvent e) { String user = getSelectedUser(); ImageIcon icon; if (groupChatRoom.isBlocked(groupJID)) { groupChatRoom.removeBlockedUser(groupJID); icon = getImageIcon(groupJID); } else { groupChatRoom.addBlockedUser(groupJID); icon = SparkRes.getImageIcon(SparkRes.BRICKWALL_IMAGE); } JLabel label = new JLabel(user, icon, JLabel.HORIZONTAL); model.setElementAt(label, index); } }; blockAction.putValue(Action.NAME, Res.getString("menuitem.block.user")); blockAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.BRICKWALL_IMAGE)); if (!selectedMyself) { if (groupChatRoom.isBlocked(groupJID)) { blockAction.putValue(Action.NAME, Res.getString("menuitem.unblock.user")); } popup.add(blockAction); } Action kickAction = new AbstractAction() { private static final long serialVersionUID = 5769982955040961189L; public void actionPerformed(ActionEvent actionEvent) { kickUser(selectedUser); } }; kickAction.putValue(Action.NAME, Res.getString("menuitem.kick.user")); kickAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.SMALL_DELETE)); if (iamModerator && !userIsAdmin && !selectedMyself) { popup.add(kickAction); } // Handle Voice Operations Action voiceAction = new AbstractAction() { private static final long serialVersionUID = 7628207942009369329L; public void actionPerformed(ActionEvent actionEvent) { if (userManager.hasVoice(groupChatRoom, selectedUser)) { revokeVoice(selectedUser); } else { grantVoice(selectedUser); } Collections.sort(users, labelComp); } }; voiceAction.putValue(Action.NAME, Res.getString("menuitem.voice")); voiceAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.MEGAPHONE_16x16)); if (iamModerator && !userIsModerator && !selectedMyself) { if (userManager.hasVoice(groupChatRoom, selectedUser)) { voiceAction.putValue(Action.NAME, Res.getString("menuitem.revoke.voice")); } else { voiceAction.putValue(Action.NAME, Res.getString("menuitem.grant.voice")); } popup.add(voiceAction); } Action banAction = new AbstractAction() { private static final long serialVersionUID = 4290194898356641253L; public void actionPerformed(ActionEvent actionEvent) { banUser(selectedUser); } }; banAction.putValue(Action.NAME, Res.getString("menuitem.ban.user")); banAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.RED_FLAG_16x16)); if (iamAdminOrOwner && !userIsModerator && !selectedMyself) { popup.add(banAction); } JMenu affiliationMenu = new JMenu(Res.getString("menuitem.affiliation")); affiliationMenu.setIcon(SparkRes.getImageIcon(SparkRes.MODERATOR_IMAGE)); Action memberAction = new AbstractAction() { private static final long serialVersionUID = -2528887841227305432L; @Override public void actionPerformed(ActionEvent e) { if (!userIsMember) { grantMember(selectedUser); } else { revokeMember(selectedUser); } Collections.sort(users, labelComp); } }; memberAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.STAR_YELLOW_IMAGE)); if(iamAdminOrOwner && !userIsMember) { memberAction.putValue(Action.NAME,Res.getString("menuitem.grant.member")); affiliationMenu.add(memberAction); } else if(iamAdminOrOwner && userIsMember && !selectedMyself) { memberAction.putValue(Action.NAME,Res.getString("menuitem.revoke.member")); affiliationMenu.add(memberAction); } Action moderatorAction = new AbstractAction() { private static final long serialVersionUID = 8162535640460764896L; public void actionPerformed(ActionEvent actionEvent) { if (!userIsModerator) { grantModerator(selectedUser); } else { revokeModerator(selectedUser); } Collections.sort(users, labelComp); } }; moderatorAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.STAR_MODERATOR)); if (iamAdminOrOwner && !userIsModerator && !userIsAdmin && !userIsOwner) { moderatorAction.putValue(Action.NAME, Res.getString("menuitem.grant.moderator")); affiliationMenu.add(moderatorAction); } else if (iamAdminOrOwner && userIsModerator && !selectedMyself) { moderatorAction.putValue(Action.NAME, Res.getString("menuitem.revoke.moderator")); affiliationMenu.add(moderatorAction); } Action adminAction = new AbstractAction() { private static final long serialVersionUID = 3672121864443182872L; @Override public void actionPerformed(ActionEvent e) { if (!userIsAdmin) { grantAdmin(selectedUser); } else { revokeAdmin(selectedUser); } Collections.sort(users, labelComp); } }; adminAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.STAR_ADMIN)); if(iamAdminOrOwner && !userIsAdmin && !userIsOwner) { adminAction.putValue(Action.NAME, Res.getString("menuitem.grant.admin")); affiliationMenu.add(adminAction); } else if(iamAdminOrOwner && !selectedMyself ) { adminAction.putValue(Action.NAME, Res.getString("menuitem.revoke.admin")); affiliationMenu.add(adminAction); } Action ownerAction = new AbstractAction() { private static final long serialVersionUID = 3672121864443182872L; @Override public void actionPerformed(ActionEvent e) { if (!userIsOwner) { grantOwner(selectedUser); } else { revokeOwner(selectedUser); } Collections.sort(users, labelComp); } }; ownerAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.STAR_OWNER)); if( iamOwner && !userIsOwner) { ownerAction.putValue(Action.NAME, Res.getString("menuitem.grant.owner")); affiliationMenu.add(ownerAction); } else if(iamOwner && !selectedMyself ) { ownerAction.putValue(Action.NAME, Res.getString("menuitem.revoke.owner")); affiliationMenu.add(ownerAction); } if(affiliationMenu.getItemCount()>0) popup.add(affiliationMenu); // Handle Unbanning of users. Action unbanAction = new AbstractAction() { private static final long serialVersionUID = 3672121864443182872L; public void actionPerformed(ActionEvent actionEvent) { String jid = ((JMenuItem) actionEvent.getSource()) .getText(); unbanUser(jid); } }; if (iamAdmin || iamOwner) { JMenu unbanMenu = new JMenu(Res.getString("menuitem.unban")); Iterator<Affiliate> bannedUsers = null; try { bannedUsers = chat.getOutcasts().iterator(); } catch (XMPPException e) { Log.error("Error loading all banned users", e); } while (bannedUsers != null && bannedUsers.hasNext()) { Affiliate bannedUser = bannedUsers.next(); ImageIcon icon = SparkRes.getImageIcon(SparkRes.RED_BALL); JMenuItem bannedItem = new JMenuItem(bannedUser.getJid(), icon); unbanMenu.add(bannedItem); bannedItem.addActionListener(unbanAction); } if (unbanMenu.getMenuComponentCount() > 0) { popup.add(unbanMenu); } } } Action inviteAction = new AbstractAction() { private static final long serialVersionUID = 2240864466141501086L; public void actionPerformed(ActionEvent actionEvent) { ConferenceUtils.inviteUsersToRoom( groupChatRoom.getConferenceService(), groupChatRoom.getRoomname(), null, false); } }; inviteAction.putValue(Action.NAME, Res.getString("menuitem.invite.users")); inviteAction.putValue(Action.SMALL_ICON, SparkRes.getImageIcon(SparkRes.CONFERENCE_IMAGE_16x16)); if (index != -1) { popup.addSeparator(); } popup.add(inviteAction); popup.show(participantsList, evt.getX(), evt.getY()); } public void setNicknameChangeAllowed(boolean allowed) { allowNicknameChange = allowed; } public int getIndex(String name) { for (int i = 0; i < model.getSize(); i++) { JLabel label = (JLabel) model.getElementAt(i); if (label.getText().equals(name)) { return i; } } return -1; } /** * Removes a user from the participant list based on their displayed name. * * @param displayName * the users displayed name to remove. */ public synchronized void removeUser(String displayName) { try { for (int i = 0; i < users.size(); i++) { JLabel label = users.get(i); if (label.getText().equals(displayName)) { users.remove(label); model.removeElement(label); } } for (int i = 0; i < model.size(); i++) { JLabel label = (JLabel) model.getElementAt(i); if (label.getText().equals(displayName)) { users.remove(label); model.removeElement(label); } } } catch (Exception e) { Log.error(e); } } /** * Adds a new user to the participant list. * * @param userIcon * the icon to use initially. * @param nickname * the users nickname. */ public synchronized void addUser(Icon userIcon, String nickname) { try { final JLabel user = new JLabel(nickname, userIcon, JLabel.HORIZONTAL); users.add(user); // Sort users alpha. Collections.sort(users, labelComp); // Add to the correct position in the model. final int index = users.indexOf(user); model.insertElementAt(user, index); } catch (Exception e) { Log.error(e); } } /** * Sorts ContactItems. */ final Comparator<JLabel> labelComp = new Comparator<JLabel>() { public int compare(JLabel item1, JLabel item2) { if (_localPreferences.isShowingRoleIcons()) { return compareWithRole(item1, item2); } else { return compareWithoutRole(item1.getText(), item2.getText()); } } private int compareWithoutRole(String s1, String s2) { return (s1.toLowerCase().compareTo(s2.toLowerCase())); } /** * Comparaes 2 items by their Role and Affiliation<br> * affiliation > role<br> * owner > admin > moderator > member > participant > visitor * @param item1 * @param item2 * @return -1, 0 or 1 */ private int compareWithRole(JLabel item1, JLabel item2) { int user1 = 100; int user2 = 100; try { // append Room-JID to UserLabel String jid1 = chat.getRoom() + "/" + item1.getText(); String jid2 = chat.getRoom() + "/" + item2.getText(); user1 = getCompareValue(jid1); user2 = getCompareValue(jid2); } catch (Exception e) { // Sometimes theres no Occupant with that jid, dunno why } int result = 0; if (user1 == user2) { result = compareWithoutRole(item1.getText(), item2.getText()); } else { // a=owner,b=admin, m=moderator, n=member , p=participant, v=visitor // a < b < m < n < p < v if (user1 < user2) result = -1; if (user1 > user2) result = 1; } return result; } }; /** * check if we have an affiliation to this room<br> * and map it to an integer<br> * 0=owner,1=admin.....5=visitor<br> */ private int getCompareValue(String jid) { int result = 100; String affi = usersandRoles.get(jid).split(",")[0]; String role = usersandRoles.get(jid).split(",")[1]; if (affi == null) affi = "z"; if (role == null) role = "z"; switch (affi.charAt(0)) { case 'o': result = 0; break; // owner case 'a': result = 1; break; // admin // Moderator is in between with 2 case 'm': result = 3; break; // member default: result = 100; } if (affi.equalsIgnoreCase("none")) { switch (role.charAt(0)) { case 'm': result = 2; break; // moderator // Member is in between with 3 case 'p': result = 4; break; // participant case 'v': result = 5; break; // visitor default: result = 100; } } if (affi.equalsIgnoreCase("member") && role.charAt(0) == 'm') { result = 2; } return result; } /** * The <code>JLabelIconRenderer</code> is the an implementation of * ListCellRenderer to add icons w/ associated text in JComboBox and JList. * * @author Derek DeMoro */ public class ParticipantRenderer extends JLabel implements ListCellRenderer { private static final long serialVersionUID = -7509947975798079141L; /** * Construct Default JLabelIconRenderer. */ public ParticipantRenderer() { setOpaque(true); } public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { if (isSelected) { setBackground(list.getSelectionBackground()); setForeground(list.getSelectionForeground()); } else { setBackground(list.getBackground()); setForeground(list.getForeground()); } JLabel label = (JLabel) value; setText(label.getText()); setIcon(label.getIcon()); return this; } } protected GroupChatRoom getGroupChatRoom() { return groupChatRoom; } protected ImageTitlePanel getAgentInfoPanel() { return agentInfoPanel; } protected MultiUserChat getChat() { return chat; } protected Map<String, String> getUserMap() { return userMap; } protected DefaultListModel getModel() { return model; } protected JXList getParticipantsList() { return participantsList; } protected PacketListener getListener() { return listener; } protected Map<String, String> getInvitees() { return invitees; } protected boolean isAllowNicknameChange() { return allowNicknameChange; } protected DiscoverInfo getRoomInformation() { return roomInformation; } protected List<JLabel> getUsers() { return users; } protected HashMap<String, String> getUsersandRoles() { return usersandRoles; } protected Comparator<JLabel> getLabelComp() { return labelComp; } }