/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd * * 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 net.java.sip.communicator.impl.gui.utils; import java.awt.*; import java.awt.event.*; import javax.swing.*; import net.java.sip.communicator.impl.gui.*; import net.java.sip.communicator.impl.gui.main.contactlist.*; import net.java.sip.communicator.plugin.desktoputil.*; import net.java.sip.communicator.service.gui.*; import net.java.sip.communicator.service.gui.event.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.skin.*; import java.util.*; import java.util.List; /** * The invite dialog is a widget that shows a list of contacts, from which the * user could pick in order to create a conference chat or call. * * @author Yana Stamcheva * @author Adam Netocny */ public class InviteDialog extends SIPCommDialog implements Skinnable, ContactListContainer { private static final long serialVersionUID = 0L; /** * Text area where user can specify a reason for the invitation. */ private final JTextArea reasonArea = new JTextArea(); /** * The button, which performs the invite. */ protected final JButton inviteButton = new JButton( GuiActivator.getResources().getI18NString("service.gui.INVITE")); /** * The button, which cancels the operation. */ private final JButton cancelButton = new JButton( GuiActivator.getResources().getI18NString("service.gui.CANCEL")); /** * The search field. */ private final SearchField searchField; /** * The source contact list. */ protected ContactList srcContactList; /** * The destination contact list. */ protected ContactList destContactList; /** * The invite contact transfer handler. */ private InviteContactTransferHandler inviteContactTransferHandler; /** * Currently selected protocol provider. */ private ProtocolProviderService currentProvider; /** * Icon label. */ private final JLabel iconLabel; /** * The description text. */ protected final JTextArea infoTextArea; /** * Constructs an <tt>InviteDialog</tt>. * * @param title the title to show on the top of this dialog */ public InviteDialog (String title, boolean enableReason) { this.setModal(false); this.setTitle(title); TransparentPanel mainPanel = new TransparentPanel(new BorderLayout(5, 5)); TransparentPanel northPanel = new TransparentPanel(new BorderLayout(10, 10)); mainPanel.setPreferredSize(new Dimension(450, 350)); mainPanel.setBorder( BorderFactory.createEmptyBorder(15, 15, 15, 15)); infoTextArea = new JTextArea(); infoTextArea.setText(GuiActivator.getResources() .getI18NString("service.gui.INVITE_CONTACT_MSG")); infoTextArea.setFont(infoTextArea.getFont().deriveFont(Font.BOLD)); infoTextArea.setLineWrap(true); infoTextArea.setOpaque(false); infoTextArea.setWrapStyleWord(true); infoTextArea.setEditable(false); iconLabel = new JLabel(new ImageIcon( ImageLoader.getImage(ImageLoader.INVITE_DIALOG_ICON))); northPanel.add(iconLabel, BorderLayout.WEST); northPanel.add(infoTextArea, BorderLayout.CENTER); TransparentPanel buttonsPanel = new TransparentPanel(new FlowLayout(FlowLayout.RIGHT)); buttonsPanel.add(inviteButton); buttonsPanel.add(cancelButton); inviteButton.setMnemonic( GuiActivator.getResources().getI18nMnemonic("service.gui.INVITE")); cancelButton.setMnemonic( GuiActivator.getResources().getI18nMnemonic("service.gui.CANCEL")); Component contactListComponent = createSrcContactListComponent(); ContactListSearchFilter inviteFilter = new InviteContactListFilter(srcContactList); srcContactList.setDefaultFilter(inviteFilter); searchField = new SearchField(null, inviteFilter, false, false); searchField.setPreferredSize(new Dimension(200, 25)); searchField.setContactList(srcContactList); searchField.addFocusListener(new FocusAdapter() { /** * Removes all other selections. * @param e the <tt>FocusEvent</tt> that notified us */ @Override public void focusGained(FocusEvent e) { srcContactList.removeSelection(); } }); TransparentPanel leftPanel = new TransparentPanel(new BorderLayout(5, 5)); leftPanel.add(searchField, BorderLayout.NORTH); leftPanel.add(contactListComponent); JPanel listPanel = new JPanel(new GridLayout(0, 2, 5, 5)); listPanel.setPreferredSize(new Dimension(400, 200)); listPanel.add(leftPanel); listPanel.add(createDestContactListComponent()); listPanel.setOpaque(false); // Add remove buttons panel. JPanel addRemoveButtonsPanel = new JPanel(new GridLayout(0, 2, 5, 5)); addRemoveButtonsPanel.setOpaque(false); JButton addContactButton = new JButton( GuiActivator.getResources().getI18NString("service.gui.ADD")); JButton removeContactButton = new JButton( GuiActivator.getResources().getI18NString("service.gui.REMOVE")); addRemoveButtonsPanel.add(addContactButton); addRemoveButtonsPanel.add(removeContactButton); addContactButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { List<UIContact> selectedContacts = srcContactList.getSelectedContacts(); if (selectedContacts != null && selectedContacts.size() > 0) moveContactsFromLeftToRight(selectedContacts.iterator()); } }); removeContactButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { List<UIContact> selectedContacts = destContactList.getSelectedContacts(); if (selectedContacts != null && selectedContacts.size() > 0) moveContactsFromRightToLeft(selectedContacts.iterator()); } }); TransparentPanel centerPanel = new TransparentPanel(new BorderLayout()); centerPanel.add(listPanel, BorderLayout.CENTER); centerPanel.add(addRemoveButtonsPanel, BorderLayout.SOUTH); TransparentPanel southPanel = new TransparentPanel(new BorderLayout()); southPanel.add(buttonsPanel, BorderLayout.SOUTH); if (enableReason) { this.reasonArea.setBorder(BorderFactory.createTitledBorder( GuiActivator.getResources() .getI18NString("service.gui.INVITE_REASON"))); southPanel.add(reasonArea, BorderLayout.CENTER); } mainPanel.add(northPanel, BorderLayout.NORTH); mainPanel.add(centerPanel, BorderLayout.CENTER); mainPanel.add(southPanel, BorderLayout.SOUTH); this.getContentPane().add(mainPanel); initTransferHandler(); KeyboardFocusManager keyManager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); ContactListSearchKeyDispatcher clKeyDispatcher = new ContactListSearchKeyDispatcher( keyManager, searchField, this); clKeyDispatcher.setContactList(srcContactList); keyManager.addKeyEventDispatcher(clKeyDispatcher); } /** * Returns the reason of this invite, if the user has specified one. * * @return the reason of this invite */ public String getReason() { return reasonArea.getText(); } /** * Adds an <tt>ActionListener</tt> to the contained "Invite" button. * * @param l the <tt>ActionListener</tt> to add */ public void addInviteButtonListener(ActionListener l) { this.inviteButton.addActionListener(l); } /** * Adds an <tt>ActionListener</tt> to the contained "Cancel" button. * * @param l the <tt>ActionListener</tt> to add */ public void addCancelButtonListener(ActionListener l) { this.cancelButton.addActionListener(l); } /** * Closes this dialog by clicking on the "Cancel" button. * * @param isEscaped indicates if this <tt>close</tt> is provoked by an * escape */ @Override protected void close(boolean isEscaped) { this.cancelButton.doClick(); } /** * Sets the current provider selected for this invite dialog. * * @param protocolProvider the protocol provider selected for this invite * dialog */ protected void setCurrentProvider(ProtocolProviderService protocolProvider) { this.currentProvider = protocolProvider; inviteContactTransferHandler.setBackupProvider(currentProvider); } /** * Moves contacts from the left list to the right. * * @param contacts an Iterator over a list of <tt>UIContact</tt>s */ private void moveContactsFromLeftToRight(Iterator<UIContact> contacts) { while (contacts.hasNext()) { moveContactFromLeftToRight(contacts.next()); } } /** * Moves the given <tt>UIContact</tt> from left list to the right. * * @param uiContact the contact to move */ protected void moveContactFromLeftToRight(UIContact uiContact) { destContactList.addContact( new InviteUIContact(uiContact, currentProvider), null, false, false); } /** * Moves contacts from the right list to the left. * * @param contacts an Iterator over a list of <tt>UIContact</tt>s */ protected void moveContactsFromRightToLeft(Iterator<UIContact> contacts) { while (contacts.hasNext()) { moveContactFromRightToLeft(contacts.next()); } } /** * Moves the given <tt>UIContact</tt> from left list to the right. * * @param uiContact the contact to move */ private void moveContactFromRightToLeft(UIContact uiContact) { destContactList.removeContact(uiContact); } /** * Reloads icon for icon label. */ public void loadSkin() { iconLabel.setIcon(new ImageIcon( ImageLoader.getImage(ImageLoader.INVITE_DIALOG_ICON))); } /** * Creates the source contact list component. * * @return the created contact list component */ private Component createSrcContactListComponent() { srcContactList = GuiActivator.getUIService().createContactListComponent(this); srcContactList.setDragEnabled(true); srcContactList.setRightButtonMenuEnabled(false); srcContactList.setContactButtonsVisible(false); srcContactList.setMultipleSelectionEnabled(true); srcContactList.addContactListListener(new ContactListListener() { public void groupSelected(ContactListEvent evt) {} public void groupClicked(ContactListEvent evt) {} public void contactSelected(ContactListEvent evt) {} public void contactClicked(ContactListEvent evt) { if (evt.getClickCount() > 1) moveContactFromLeftToRight(evt.getSourceContact()); } }); // By default we set the current filter to be the presence filter. JScrollPane contactListScrollPane = new JScrollPane(); contactListScrollPane.setOpaque(false); contactListScrollPane.getViewport().setOpaque(false); contactListScrollPane.getViewport().add(srcContactList.getComponent()); contactListScrollPane.getViewport().setBorder(null); contactListScrollPane.setViewportBorder(null); contactListScrollPane.setBorder(null); return contactListScrollPane; } /** * Creates the destination contact list component. * * @return the created contact list component */ private Component createDestContactListComponent() { destContactList = GuiActivator.getUIService().createContactListComponent(this); destContactList.removeAllContactSources(); destContactList.setContactButtonsVisible(false); destContactList.setRightButtonMenuEnabled(false); destContactList.setMultipleSelectionEnabled(true); destContactList.addContactListListener(new ContactListListener() { public void groupSelected(ContactListEvent evt) {} public void groupClicked(ContactListEvent evt) {} public void contactSelected(ContactListEvent evt) {} public void contactClicked(ContactListEvent evt) { if (evt.getClickCount() > 1) moveContactFromRightToLeft(evt.getSourceContact()); } }); // By default we set the current filter to be the presence filter. JScrollPane contactListScrollPane = new JScrollPane(); contactListScrollPane.setOpaque(false); contactListScrollPane.getViewport().setOpaque(false); contactListScrollPane.getViewport().add(destContactList.getComponent()); contactListScrollPane.getViewport().setBorder(null); contactListScrollPane.setViewportBorder(null); contactListScrollPane.setBorder(null); return contactListScrollPane; } /** * Called when the ENTER key was typed when this container was the focused * container. Performs the appropriate actions depending on the current * state of the contained contact list. */ public void enterKeyTyped() { List<UIContact> selectedContacts = srcContactList.getSelectedContacts(); if (selectedContacts == null) return; moveContactsFromLeftToRight(selectedContacts.iterator()); } /** * Called when the CTRL-ENTER or CMD-ENTER keys were typed when this * container was the focused container. Performs the appropriate actions * depending on the current state of the contained contact list. */ public void ctrlEnterKeyTyped() {} /** * Initializes the transfer handler. */ private void initTransferHandler() { inviteContactTransferHandler = new InviteContactTransferHandler( destContactList, InviteContactTransferHandler.DEST_TRANSFER_HANDLER, true); InviteContactTransferHandler srcContactTransferHandler = new InviteContactTransferHandler( srcContactList, InviteContactTransferHandler.SOURCE_TRANSFER_HANDLER, true); if (srcContactList.getComponent() instanceof JComponent) ((JComponent) srcContactList).setTransferHandler( srcContactTransferHandler); if (destContactList.getComponent() instanceof JComponent) ((JComponent) destContactList).setTransferHandler( inviteContactTransferHandler); } /** * Returns the text currently shown in the search field. * @return the text currently shown in the search field */ public String getCurrentSearchText() { return searchField.getText(); } /** * Clears the current text in the search field. */ public void clearCurrentSearchText() { searchField.setText(""); } /** * Returns <tt>true</tt> if there's any currently selected menu related to * this <tt>ContactListContainer</tt>, <tt>false</tt> - otherwise. * * @return <tt>true</tt> if there's any currently selected menu related to * this <tt>ContactListContainer</tt>, <tt>false</tt> - otherwise */ public boolean isMenuSelected() { // This dialog has no menu bar so it will never be selected return false; } @Override public void dispose() { searchField.dispose(); super.dispose(); } }