/*
* Copyright 2004 - 2008 Christian Sprajc. All rights reserved.
*
* This file is part of PowerFolder.
*
* PowerFolder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* PowerFolder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PowerFolder. If not, see <http://www.gnu.org/licenses/>.
*
* $Id$
*/
package de.dal33t.powerfolder.ui.wizard;
import static de.dal33t.powerfolder.ui.wizard.WizardContextAttributes.FOLDERINFO_ATTRIBUTE;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import jwf.WizardPanel;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.Sizes;
import de.dal33t.powerfolder.ConfigurationEntry;
import de.dal33t.powerfolder.Controller;
import de.dal33t.powerfolder.Member;
import de.dal33t.powerfolder.PreferencesEntry;
import de.dal33t.powerfolder.light.AccountInfo;
import de.dal33t.powerfolder.light.FolderInfo;
import de.dal33t.powerfolder.message.Invitation;
import de.dal33t.powerfolder.security.FolderPermission;
import de.dal33t.powerfolder.ui.action.BaseAction;
import de.dal33t.powerfolder.ui.dialog.NodesSelectDialog2;
import de.dal33t.powerfolder.ui.widget.AutoTextField;
import de.dal33t.powerfolder.ui.widget.JButtonMini;
import de.dal33t.powerfolder.util.InvitationUtil;
import de.dal33t.powerfolder.util.LoginUtil;
import de.dal33t.powerfolder.util.Reject;
import de.dal33t.powerfolder.util.Translation;
import de.dal33t.powerfolder.util.compare.MemberComparator;
/**
* @author <a href="mailto:totmacher@powerfolder.com">Christian Sprajc </a>
* @version $Revision: 1.12 $
*/
public class SendInvitationsPanel extends PFWizardPanel {
private static final Logger LOG = Logger.getLogger(SendInvitationsPanel.class.getName());
private FolderInfo folderInfo;
private JButtonMini addButton;
private JButtonMini searchButton;
private JButtonMini removeButton;
private AutoTextField viaPowerFolderText;
private JList inviteesList;
private JScrollPane inviteesListScrollPane;
private DefaultListModel inviteesListModel;
private Invitation invitation;
private JPanel removeButtonPanel;
private DefaultComboBoxModel permissionsComboModel;
private JComboBox permissionsCombo;
public SendInvitationsPanel(Controller controller) {
super(controller);
}
/**
* Handles the invitation to nodes option.
*
* @return true if send otherwise false
*/
private boolean sendInvitation() {
if (invitation == null) {
return false;
}
String permissionText = (String) permissionsComboModel.getSelectedItem();
FolderPermission folderPermission = FolderPermission.readWrite(invitation.folder);
if (permissionText != null) {
FolderPermission readPermission = FolderPermission.read(invitation.folder);
if (readPermission.getName().equals(permissionText)) {
folderPermission = readPermission;
}
FolderPermission readWritePermission = FolderPermission.readWrite(invitation.folder);
if (readWritePermission.getName().equals(permissionText)) {
folderPermission = readWritePermission;
}
FolderPermission adminPermission = FolderPermission.admin(invitation.folder);
if (adminPermission.getName().equals(permissionText)) {
folderPermission = adminPermission;
}
}
invitation.setPermission(folderPermission);
boolean theResult = false;
Set<Member> candidates = getCandidates();
// Send invite from text or list.
if (viaPowerFolderText.getText().length() > 0) {
sendInvite(candidates, viaPowerFolderText.getText());
theResult = true;
}
for (Object o : inviteesListModel.toArray()) {
String invitee = (String) o;
sendInvite(candidates, invitee);
theResult = true;
}
return theResult;
}
/**
* Send an invite to a friend. The invitee must be in the list of friends or
* be a valid email.
*
* @param candidates
* @param invitee
*/
private void sendInvite(Collection<Member> candidates, String invitee) {
RuntimeException rte = null;
// Invitation by email
try {
InvitationUtil.invitationByServer(getController(), invitation,
invitee, false);
} catch (RuntimeException e) {
LOG.log(Level.SEVERE, "Unable to send invitation to " + invitee
+ ". " + e, e);
rte = e;
}
for (Member node : candidates) {
AccountInfo aInfo = node.getAccountInfo();
if (aInfo != null && aInfo.getDisplayName() != null
&& aInfo.getDisplayName().equalsIgnoreCase(invitee))
{
InvitationUtil.invitationToNode(getController(), invitation,
node);
}
}
// Invitation by node name
for (Member node : candidates) {
if (invitee.equalsIgnoreCase(node.getNick())) {
InvitationUtil.invitationToNode(getController(), invitation,
node);
}
}
if (rte != null) {
throw rte;
}
}
public boolean hasNext() {
return !inviteesListModel.isEmpty() || viaPowerFolderText.getText().length() > 0;
}
public WizardPanel next() {
Runnable inviteTask = new Runnable() {
public void run() {
if (!sendInvitation()) {
throw new RuntimeException(Translation.getTranslation("wizard.send_invitations.no_invitees"));
}
}
};
WizardPanel successPanel = (WizardPanel) getWizardContext()
.getAttribute(PFWizard.SUCCESS_PANEL);
return new SwingWorkerPanel(
getController(),
inviteTask,
Translation
.getTranslation("wizard.send_invitations.sending_invites"),
Translation
.getTranslation("wizard.send_invitations.sending_invites.text"),
successPanel);
}
protected JPanel buildContent() {
FormLayout layout = new FormLayout(
"140dlu, pref:grow",
"pref, 10dlu, pref, 3dlu, pref, max(10dlu;pref), 10dlu, pref");
PanelBuilder builder = new PanelBuilder(layout);
builder.setBorder(createFewContentBorder());
CellConstraints cc = new CellConstraints();
FormLayout layout1 = new FormLayout("pref, 3dlu, pref:grow", "pref");
PanelBuilder builder1 = new PanelBuilder(layout1);
builder1.addLabel(Translation.getTranslation("send_invitations.folder_label"), cc.xy(1, 1));
int row = 1;
builder1.addLabel(folderInfo.getName(), cc.xy(3, row));
JPanel panel1 = builder1.getPanel();
panel1.setOpaque(false);
builder.add(panel1, cc.xy(1, row));
row += 2;
FormLayout layout2 = new FormLayout("pref, 3dlu, pref:grow, 3dlu, pref, pref", "pref");
PanelBuilder builder2 = new PanelBuilder(layout2);
builder2.addLabel(LoginUtil.getInviteUsernameLabel(getController()), cc.xy(1, 1));
builder2.add(viaPowerFolderText, cc.xy(3, 1));
builder2.add(addButton, cc.xy(5, 1));
if (PreferencesEntry.EXPERT_MODE.getValueBoolean(getController())) {
builder2.add(searchButton, cc.xy(6, 1));
}
JPanel panel2 = builder2.getPanel();
panel2.setOpaque(false);
builder.add(panel2, cc.xy(1, row));
row += 2;
inviteesListScrollPane = new JScrollPane(inviteesList);
inviteesListScrollPane.setPreferredSize(new Dimension(
getPreferredSize().width, Sizes.dialogUnitYAsPixel(40,
inviteesListScrollPane)));
builder.add(inviteesListScrollPane, cc.xy(1, row));
inviteesListScrollPane.setVisible(false);
row += 1;
FormLayout layout3 = new FormLayout("pref, pref:grow", "pref");
PanelBuilder builder3 = new PanelBuilder(layout3);
builder3.add(removeButton, cc.xy(1, 1));
removeButtonPanel = builder3.getPanel();
removeButtonPanel.setOpaque(false);
builder.add(removeButtonPanel, cc.xy(1, row));
removeButtonPanel.setVisible(false);
row += 2;
FormLayout layout4 = new FormLayout("pref, 3dlu, pref:grow", "pref");
PanelBuilder builder4 = new PanelBuilder(layout4);
builder4.add(new JLabel(Translation.getTranslation("send_invitations.permissions_label")), cc.xy(1, 1));
builder4.add(permissionsCombo, cc.xy(3, 1));
builder.add(builder4.getPanel(), cc.xy(1, row));
return builder.getPanel();
}
/**
* Initializes all necessary components
*/
protected void initComponents() {
folderInfo = (FolderInfo) getWizardContext().getAttribute(FOLDERINFO_ATTRIBUTE);
Reject.ifNull(folderInfo, "Unable to send invitation, folder is null");
// Clear folder attribute
getWizardContext().setAttribute(FOLDERINFO_ATTRIBUTE, null);
invitation = folderInfo.getFolder(getController()).createInvitation();
addButton = new JButtonMini(new MyAddAction(getController()));
removeButton = new JButtonMini(new MyRemoveAction(getController()));
searchButton = new JButtonMini(new MySearchAction(getController()));
viaPowerFolderText = new AutoTextField();
viaPowerFolderText.addKeyListener(new MyKeyListener());
inviteesListModel = new DefaultListModel();
inviteesList = new JList(inviteesListModel);
inviteesList.getSelectionModel().setSelectionMode(
ListSelectionModel.SINGLE_SELECTION);
inviteesList.getSelectionModel().addListSelectionListener(
new MyListSelectionListener());
List<String> candidateAddresses = getCandidatesAddresses();
viaPowerFolderText.setDataList(candidateAddresses);
permissionsComboModel = new DefaultComboBoxModel();
permissionsCombo = new JComboBox(permissionsComboModel);
permissionsComboModel.addElement(FolderPermission.readWrite(folderInfo).getName());
permissionsComboModel.addElement(FolderPermission.read(folderInfo).getName());
if (ConfigurationEntry.SECURITY_PERMISSIONS_SHOW_FOLDER_ADMIN.getValueBoolean(getController()))
{
permissionsComboModel.addElement(FolderPermission.admin(folderInfo).getName());
}
enableAddButton();
enableRemoveButton();
}
private List<String> getCandidatesAddresses() {
List<String> candidateAddresses = new LinkedList<String>();
for (Member friend : getController().getNodeManager().getFriends()) {
AccountInfo aInfo = friend.getAccountInfo();
if (aInfo != null && aInfo.getDisplayName() != null) {
// FIXME Shows email unscrambled!
candidateAddresses.add(0, aInfo.getDisplayName());
}
//candidateAddresses.add(friend.getNick());
}
for (Member node : getController().getNodeManager().getConnectedNodes())
{
if (!node.isOnLAN()) {
continue;
}
AccountInfo aInfo = node.getAccountInfo();
if (aInfo != null && aInfo.getDisplayName() != null) {
// FIXME Shows email unscrambled!
candidateAddresses.add(0, aInfo.getDisplayName());
}
//candidateAddresses.add(node.getNick());
}
return candidateAddresses;
}
private Set<Member> getCandidates() {
Set<Member> candidate = new TreeSet<Member>(MemberComparator.NICK);
Collections.addAll(candidate, getController().getNodeManager().getFriends());
for (Member node : getController().getNodeManager().getConnectedNodes())
{
if (!node.isOnLAN()) {
continue;
}
candidate.add(node);
}
return candidate;
}
protected String getTitle() {
return Translation.getTranslation("wizard.send_invitations.title");
}
private void enableAddButton() {
addButton.setEnabled(viaPowerFolderText.getText().length() > 0);
}
private void enableRemoveButton() {
removeButton.setEnabled(!inviteesListModel.isEmpty()
&& inviteesList.getSelectedIndex() >= 0);
}
private void processInvitee() {
String text = viaPowerFolderText.getText();
if (text.length() > 0) {
inviteesListModel.addElement(text);
inviteesListScrollPane.setVisible(true);
removeButtonPanel.setVisible(true);
viaPowerFolderText.clear();
updateButtons();
enableAddButton();
enableRemoveButton();
}
}
// /////////////////
// Inner classes //
// /////////////////
private class MyAddAction extends BaseAction {
MyAddAction(Controller controller) {
super("action_add_invitee", controller);
}
public void actionPerformed(ActionEvent e) {
processInvitee();
}
}
private class MySearchAction extends BaseAction {
MySearchAction(Controller controller) {
super("action_search_invitee", controller);
}
public void actionPerformed(ActionEvent e) {
Collection<Member> selectedMembers = new ArrayList<Member>();
NodesSelectDialog2 nsd2 = new NodesSelectDialog2(getController(),
selectedMembers);
nsd2.open();
for (Member selectedMember : selectedMembers) {
boolean got = false;
for (Object o : inviteesListModel.toArray()) {
String invitee = (String) o;
if (selectedMember.getNick().equals(invitee)) {
got = true;
break;
}
}
if (!got) {
inviteesListModel.addElement(selectedMember.getNick());
inviteesListScrollPane.setVisible(true);
removeButtonPanel.setVisible(true);
}
}
updateButtons();
}
}
private class MyRemoveAction extends BaseAction {
MyRemoveAction(Controller controller) {
super("action_remove_invitee", controller);
}
public void actionPerformed(ActionEvent e) {
int index = inviteesList.getSelectedIndex();
if (index >= 0) {
inviteesListModel.remove(index);
inviteesListScrollPane.setVisible(!inviteesListModel.isEmpty());
removeButtonPanel.setVisible(!inviteesListModel.isEmpty());
enableRemoveButton();
}
}
}
private class MyKeyListener extends KeyAdapter {
public void keyReleased(KeyEvent e) {
updateButtons();
enableAddButton();
}
}
private class MyListSelectionListener implements ListSelectionListener {
public void valueChanged(ListSelectionEvent e) {
enableRemoveButton();
updateButtons();
}
}
}