package org.limewire.ui.swing.friends.login; import static org.limewire.ui.swing.util.I18n.tr; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.Locale; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import net.miginfocom.swing.MigLayout; import org.jdesktop.application.Resource; import org.jdesktop.swingx.JXButton; import org.jdesktop.swingx.JXPanel; import org.limewire.core.settings.FriendSettings; import org.limewire.friend.api.FriendConnectionEvent; import org.limewire.friend.api.FriendConnectionFactory; import org.limewire.listener.EventListener; import org.limewire.listener.ListenerSupport; import org.limewire.listener.SwingEDTEvent; import org.limewire.ui.swing.action.AbstractAction; import org.limewire.ui.swing.components.Disposable; import org.limewire.ui.swing.components.HyperlinkButton; import org.limewire.ui.swing.components.PromptPasswordField; import org.limewire.ui.swing.components.PromptTextField; import org.limewire.ui.swing.components.decorators.ButtonDecorator; import org.limewire.ui.swing.components.decorators.TextFieldDecorator; import org.limewire.ui.swing.friends.settings.FriendAccountConfiguration; import org.limewire.ui.swing.friends.settings.FriendAccountConfigurationManager; import org.limewire.ui.swing.painter.BorderPainter.AccentType; import org.limewire.ui.swing.painter.factories.BarPainterFactory; import org.limewire.ui.swing.settings.SwingUiSettings; import org.limewire.ui.swing.util.GuiUtils; import org.limewire.ui.swing.util.I18n; import org.limewire.ui.swing.util.ResizeUtils; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; public class XMPPUserEntryLoginPanel extends JPanel implements Disposable { private static final String CUSTOM_SERVICE_NAME = "Jabber"; // Used for hack to show email/username depending on if the service is gmail or not private static final String GMAIL_SERVICE_NAME = "gmail.com"; @Resource private Font headerTextFont; @Resource private Color headerTextForeground; @Resource private Font descriptionTextFont; @Resource private Color descriptionTextForeground; @Resource private Font inputTextFont; @Resource private Color inputTextForeground; @Resource private Font goBackTextFont; @Resource(key="XMPPUserEntryLoginPanel.authFailedLabel.foreground") private Color warningForeground; @Resource(key="XMPPUserEntryLoginPanel.authFailedLabel.font") private Font warningFont; @Resource(key="XMPPUserEntryLoginPanel.authFailedLabel.icon") private Icon warningIcon; @Resource(key="XMPPUserEntryLoginPanel.signInButton.foreground") private Color signInButtonForeground; @Resource(key="XMPPUserEntryLoginPanel.signInButton.font") private Font signInButtonFont; @Resource(key="XMPPUserEntryLoginPanel.autoLoginCheckBox.icon") private Icon autoLoginCheckBoxIcon; @Resource(key="XMPPUserEntryLoginPanel.autoLoginCheckBox.selectedIcon") private Icon autoLoginCheckBoxSelectedIcon; @Resource(key="XMPPUserEntryLoginPanel.autoLoginCheckBox.font") private Font autoLoginCheckBoxFont; private static final String SIGNIN_ENABLED_TEXT = tr("Sign In"); private static final String SIGNIN_DISABLED_TEXT = tr("Signing in..."); private static final String AUTHENTICATION_ERROR = tr("Incorrect username or password."); private static final String NETWORK_ERROR = tr("Network error."); private PromptTextField serviceField; private PromptTextField usernameField; private PromptPasswordField passwordField; private JCheckBox autoLoginCheckBox; private JLabel authFailedLabel; private JXButton signInButton; private final SignInAction signinAction = new SignInAction(); private ListenerSupport<FriendConnectionEvent> connectionSupport = null; private final FriendAccountConfiguration accountConfig; private final LoginPopupPanel parent; private final FriendAccountConfigurationManager accountManager; private EventListener<FriendConnectionEvent> connectionListener; private JLabel serviceLabel; private JComponent serviceRecenter; private boolean connectionHasBeenInitiated = false; private final FriendConnectionFactory friendConnectionFactory; @Inject public XMPPUserEntryLoginPanel(@Assisted FriendAccountConfiguration accountConfig, LoginPopupPanel parent, FriendAccountConfigurationManager accountManager, ButtonDecorator buttonDecorator, TextFieldDecorator textFieldDecorator, BarPainterFactory barPainterFactory, FriendConnectionFactory friendConnectionFactory) { super(new BorderLayout()); this.accountConfig = accountConfig; this.parent = parent; this.accountManager = accountManager; this.friendConnectionFactory = friendConnectionFactory; GuiUtils.assignResources(this); JXPanel headerPanel = new JXPanel(new MigLayout("gap 10, insets 15 20 15 20")); headerPanel.setBackgroundPainter(barPainterFactory.createPopUpBarPainter()); JLabel headerLabel = new JLabel(I18n.tr("Sign in with {0}",accountConfig.getLabel())); JLabel headerIcon = new JLabel(accountConfig.getLargeIcon()); headerLabel.setFont(headerTextFont); headerLabel.setForeground(headerTextForeground); headerPanel.add(headerIcon); headerPanel.add(headerLabel); add(headerPanel, BorderLayout.NORTH); initComponents(buttonDecorator, textFieldDecorator); initServiceField(); setSignInComponentsEnabled(true); } @Inject void registerListener(ListenerSupport<FriendConnectionEvent> connectionSupport) { this.connectionSupport = connectionSupport; connectionListener = new EventListener<FriendConnectionEvent>() { @Override @SwingEDTEvent public void handleEvent(FriendConnectionEvent event) { switch(event.getType()) { case CONNECTING: connecting(); break; case CONNECTED: connected(); break; case CONNECT_FAILED: // Do not show connect failed messages from before a // connection has been attempted if (!connectionHasBeenInitiated) { break; } // Ignore duplicate events caused by authentication // errors and events caused by deliberately signing // out or switching user Exception reason = event.getException(); if(reason != null) { disconnected(reason); } } } }; connectionSupport.addListener(connectionListener); } private void initComponents(ButtonDecorator buttonDecorator, TextFieldDecorator textFieldDecorator) { serviceRecenter = new JPanel(); ResizeUtils.forceSize(serviceRecenter, new Dimension(30,30)); serviceLabel = new JLabel(tr("Domain")); serviceLabel.setFont(descriptionTextFont); serviceLabel.setForeground(descriptionTextForeground); JLabel usernameLabel = new JLabel(GMAIL_SERVICE_NAME.equals(accountConfig.getNetworkName()) ? tr("Email") : tr("Username")); usernameLabel.setFont(descriptionTextFont); usernameLabel.setForeground(descriptionTextForeground); JLabel passwordLabel = new JLabel(tr("Password")); passwordLabel.setFont(descriptionTextFont); passwordLabel.setForeground(descriptionTextForeground); /* * Populate the input fields on initialize. Otherwise, if the auto-login * option is selected in application settings and the user exits out of * the login panel with the auto-login option unchecked, settings are * cleared from application settings. */ serviceField = new PromptTextField(); textFieldDecorator.decoratePromptField(serviceField, AccentType.NONE); serviceField.setFont(inputTextFont); serviceField.setForeground(inputTextForeground); usernameField = new PromptTextField(); textFieldDecorator.decoratePromptField(usernameField, AccentType.NONE); usernameField.setFont(inputTextFont); usernameField.setForeground(inputTextForeground); usernameField.setText(accountConfig.getUserInputLocalID()); passwordField = new PromptPasswordField(); textFieldDecorator.decoratePromptField(passwordField, AccentType.NONE); passwordField.setFont(inputTextFont); passwordField.setForeground(inputTextForeground); passwordField.setAction(signinAction); passwordField.setText(accountConfig.getPassword()); ResizeUtils.forceSize(serviceField, new Dimension(224, 26)); ResizeUtils.forceSize(usernameField, new Dimension(224, 26)); ResizeUtils.forceSize(passwordField, new Dimension(224, 26)); autoLoginCheckBox = new JCheckBox(tr("Sign in when I start LimeWire"), true); autoLoginCheckBox.setFont(autoLoginCheckBoxFont); autoLoginCheckBox.setIcon(autoLoginCheckBoxIcon); autoLoginCheckBox.setSelectedIcon(autoLoginCheckBoxSelectedIcon); autoLoginCheckBox.setSelected(accountManager.getAutoLoginConfig() != null); autoLoginCheckBox.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { // When the user clears the auto-login checkbox, // forget the auto-login config if(!autoLoginCheckBox.isSelected()) { accountManager.setAutoLoginConfig(null); } SwingUiSettings.REMEMBER_ME_CHECKED.setValue(autoLoginCheckBox.isSelected()); } }); autoLoginCheckBox.setOpaque(false); // Hack to get the enter key to start login for JCheckBox autoLoginCheckBox.addKeyListener(new KeyListener() { @Override public void keyPressed(KeyEvent e) { } @Override public void keyReleased(KeyEvent e) { } @Override public void keyTyped(KeyEvent e) { if (e.getKeyChar() == KeyEvent.VK_ENTER) { login(); } } }); signInButton = new JXButton(signinAction); buttonDecorator.decorateGreenFullButton(signInButton); signInButton.setFont(signInButtonFont); signInButton.setForeground(signInButtonForeground); signInButton.setBorder(BorderFactory.createEmptyBorder(0,15,2,15)); ResizeUtils.looseForceHeight(signInButton, 32); authFailedLabel = new JLabel(); authFailedLabel.setVisible(false); authFailedLabel.setForeground(warningForeground); authFailedLabel.setFont(warningFont); authFailedLabel.setIcon(warningIcon); HyperlinkButton goBackButton = new HyperlinkButton(new AbstractAction(I18n.tr("Choose another account")) { @Override public void actionPerformed(ActionEvent arg0) { parent.restart(); } }); goBackButton.setFont(goBackTextFont); JPanel contentPanel = new JPanel(new MigLayout("gap 0, insets 10, align center")); contentPanel.add(authFailedLabel, "dock north, gapleft 2, hidemode 3, gapbottom 3, wrap"); contentPanel.add(serviceLabel, "hidemode 3, wrap"); contentPanel.add(serviceField, "gapbottom 10, hidemode 3, grow, wrap"); contentPanel.add(usernameLabel, "wrap"); contentPanel.add(usernameField, "gapbottom 10, grow, wrap"); contentPanel.add(passwordLabel, "wrap"); contentPanel.add(passwordField, "gapbottom 6, grow, wrap"); contentPanel.add(autoLoginCheckBox, "gapbottom 10, wmin 0, wrap"); contentPanel.add(signInButton, "wrap"); contentPanel.add(serviceRecenter, "hidemode 3, wrap"); JPanel bottomPanel = new JPanel(new MigLayout("insets 0, gap 0, align center")); bottomPanel.add(goBackButton, "gapbottom 10"); add(contentPanel, BorderLayout.CENTER); add(bottomPanel, BorderLayout.SOUTH); } private void setSignInComponentsEnabled(boolean isEnabled) { signinAction.setEnabled(isEnabled); signinAction.putValue(Action.NAME, isEnabled ? SIGNIN_ENABLED_TEXT : SIGNIN_DISABLED_TEXT); serviceField.setEnabled(isEnabled); usernameField.setEnabled(isEnabled); passwordField.setEnabled(isEnabled); autoLoginCheckBox.setEnabled(isEnabled); } private void initServiceField() { if(accountConfig.getLabel().equals(CUSTOM_SERVICE_NAME)) { serviceLabel.setVisible(true); serviceField.setVisible(true); serviceRecenter.setVisible(false); } else { serviceLabel.setVisible(false); serviceField.setVisible(false); serviceRecenter.setVisible(true); } } private void login() { FriendSettings.EVER_TRIED_TO_SIGN_IN.setValue(true); String user = usernameField.getText().trim(); String password = new String(passwordField.getPassword()); if(user.equals("") || password.equals("")) { return; } if(accountConfig.getLabel().equals("Jabber")) { String service = serviceField.getText().trim(); if(service.equals("")) return; accountConfig.setServiceName(service); } accountConfig.setUsername(user); accountConfig.setPassword(password); if(autoLoginCheckBox.isSelected()) { // Set this as the auto-login account accountManager.setAutoLoginConfig(accountConfig); } else { // If there was previously an auto-login account, delete it accountManager.setAutoLoginConfig(null); } authFailedLabel.setVisible(false); validate(); repaint(); friendConnectionFactory.login(accountConfig); } void connected() { FriendSettings.EVER_SIGNED_IN.setValue(true); parent.finished(); } void disconnected(Exception reason) { setSignInComponentsEnabled(true); if(reason !=null && reason.getMessage() != null && reason.getMessage().toLowerCase(Locale.US).contains("auth")) { authFailedLabel.setText(AUTHENTICATION_ERROR); passwordField.setText(""); } else { authFailedLabel.setText(NETWORK_ERROR); } authFailedLabel.setVisible(true); } public void connecting() { connectionHasBeenInitiated = true; setSignInComponentsEnabled(false); } @Override public boolean requestFocusInWindow() { if (serviceField.isVisible()) { return serviceField.requestFocusInWindow(); } else { return usernameField.requestFocusInWindow(); } } class SignInAction extends AbstractAction { public SignInAction() { super(); } public void actionPerformed(ActionEvent e) { login(); } } @Override public void dispose() { connectionSupport.removeListener(connectionListener); } }