/*
* org.openmicroscopy.shoola.util.ui.login.ScreenLogin
*
*------------------------------------------------------------------------------
* Copyright (C) 2006-2014 University of Dundee. All rights reserved.
*
*
* This program 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; either version 2 of the License, or
* (at your option) any later version.
* This program 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 this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*------------------------------------------------------------------------------
*/
package org.openmicroscopy.shoola.util.ui.login;
//Java imports
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.prefs.Preferences;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
//Third-party libraries
import org.openmicroscopy.shoola.util.CommonsLangUtils;
//Application-internal dependencies
import org.openmicroscopy.shoola.util.StringComparator;
import org.openmicroscopy.shoola.util.ui.IconManager;
import org.openmicroscopy.shoola.util.ui.UIUtilities;
/**
* The login frame.
*
* @author Jean-Marie Burel
* <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @author Donald MacDonald
* <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a>
* @version 3.0
* <small>
* (<b>Internal version:</b> $Revision: $Date: $)
* </small>
* @since OME3.0
*/
public class ScreenLogin
extends JFrame
implements ActionListener, DocumentListener, PropertyChangeListener
{
/** Bounds property indicating this window is moved to the front. */
public static final String TO_FRONT_PROPERTY = "toFront";
/** Bounds property indicating to log in. */
public static final String LOGIN_PROPERTY = "login";
/** Bounds property indicating to log in. */
public static final String QUIT_PROPERTY = "quit";
/** Identifies the user name field. */
public static final int USERNAME_FIELD = 0;
/** Identifies the password field. */
public static final int PASSWORD_FIELD = 1;
/** Default text if no server. */
public static final String DEFAULT_SERVER = "Add a new server ->";
/** The font color for text. */
static final Color TEXT_COLOR = new Color(110, 102, 96);
/** The font color for foot note. */
static final Color FOOT_NOTE_COLOR = new Color(156, 165, 174);
/** The default size of the window. */
static final Dimension DEFAULT_SIZE = new Dimension(551, 113);
/** The default color for the foreground. */
private final static Color FOREGROUND_COLOR = Color.DARK_GRAY;
/** The property name for the user who connects to <i>OMERO</i>. */
private static final String OMERO_USER = "omeroUser";
/** The property name for the connection speed used to connect to server. */
private static final String OMERO_CONNECTION_SPEED =
"omeroConnectionSpeed";
/** The property name for the user who connects to <i>OMERO</i>. */
private static final String OMERO_USER_GROUP = "omeroUserGroup";
/**
* The property name to indicated that the data transfer is
* encrypted or not.
*/
private static final String OMERO_TRANSFER_ENCRYPTED =
"omeroTransferEncrypted";
/** Indent value for text. */
private static final int TEXT_INDENT = 15;
/** The style of the font for the version. */
private static final int VERSION_FONT_STYLE = Font.BOLD;
/** The user name text. */
private static final String USER_TEXT = "Username: ";
/** The password text. */
private static final String PASSWORD_TEXT = "Password: ";
/** The number of column of the text field. */
private static final int TEXT_COLUMN = 12;
/** The maximum number of characters.*/
private static final int MAX_CHAR = 50;
/** Text field to enter the login user name. */
private static JTextField user;
/** Password field to enter login password. */
private JPasswordField pass;
/** Button to bring up the <code>ServerDialog</code>. */
private JButton configButton;
/** Button to login to server. */
private JButton login;
/** Button to quit the application. */
private JButton cancel;
/** The name of the server or default value if none already defined. */
private String serverName;
/** Field hosting the server text. */
private static JTextPane serverText;
/** The UI component hosting the server text. */
private JPanel serverTextPane;
/** Field hosting the server text. */
private JLabel connectionSpeedText;
/** UI component hosting the version of the software. */
private JTextPane versionInfo;
/** Reference to the editor hosting the table. */
private ServerEditor editor;
/** The selected connection speed. */
private int speedIndex;
/** The port value. */
private int selectedPort;
/** Indicates to show or hide the connection speed option. */
private boolean connectionSpeed;
/** The default foreground color. */
private Color defaultForeground;
/** The groups the user is a member of. */
private JComboBox groupsBox;
//private JButton groupsBox;
/** The component displaying the login text. */
private JTextPane pleaseLogIn;
/** The groups the user is member of. */
private Map<Long, String> groups;
/** The name read from the system property if previously set. */
private String originalName;
/** The name read from the system property if previously set. */
private String originalServerName;
/** The component displaying the login option. */
private List<JComponent> ref;
/** The component displaying the controls. */
private JPanel mainPanel;
/** The possible groups. */
private String[] groupValues;
/**
* Button indicating that the transfer of data is secured or not
* depending on the selected status.
*/
private JButton encryptedButton;
/** Flag indicating that the transfer of data is secured or not. */
private boolean encrypted;
/** The map hosting the real group names.*/
private Map<Integer, String> groupNames;
/** The layered hosting the various UI components. */
private JLayeredPane layers;
/** Displays the name of the task that is currently being executed. */
private JLabel currentTask;
/** Provides feedback on the state of the initialization process. */
private JProgressBar progressBar;
/** Indicates when attempting to log in.*/
private boolean loginAttempt;
/** The listener to encrypt the data transfer.*/
private ActionListener encryptionListener;
/** Flag indicating to modify the host.*/
private boolean hostConfigurable;
/** The default server name from the configuration file.*/
private String configureServerName;
/** List of components to show or hide depending on connection status.*/
private List<JComponent> components;
/** Quits the application. */
private void quit()
{
String usr = user.getText().trim();
String server = serverText.getText();
if (usr == null) usr = "";
if (server == null) server = "";
firePropertyChange(QUIT_PROPERTY, Boolean.valueOf(false),
Boolean.valueOf(true));
}
/** Attempts to log in. */
private void login()
{
firePropertyChange(TO_FRONT_PROPERTY, Boolean.valueOf(false),
Boolean.valueOf(true));
requestFocusOnField();
StringBuffer buf = new StringBuffer();
buf.append(pass.getPassword());
String usr = user.getText(), psw = buf.toString();
String s = serverText.getText();
if (CommonsLangUtils.isBlank(usr) || CommonsLangUtils.isBlank(s) ||
s.trim().equals(DEFAULT_SERVER)) {
requestFocusOnField();
return;
}
if (usr != null) usr = usr.trim();
if (s != null) s = s.trim();
setControlsEnabled(false);
LoginCredentials lc;
if (groupsBox == null) {
lc = new LoginCredentials(usr, psw, s, speedIndex,
selectedPort, encrypted);
} else {
long id = -1L;
if (hasGroupOption() && groupsBox.isVisible())
//id = getGroupId(groupsBox.getText());
id = getGroupId(groupNames.get(groupsBox.getSelectedIndex()));
lc = new LoginCredentials(usr, psw, s, speedIndex,
selectedPort, id, encrypted);
}
setUserName(usr);
setEncrypted();
setControlsEnabled(false);
loginAttempt = true;
login.setEnabled(false);
firePropertyChange(LOGIN_PROPERTY, null, lc);
}
/**
* Returns the identifier of the group corresponding to the passed value.
*
* @param value The name of the
* @return
*/
private Long getGroupId(String value)
{
Entry<Long, String> entry;
Iterator<Entry<Long, String>> i = groups.entrySet().iterator();
while (i.hasNext()) {
entry = i.next();
if (entry.getValue().equals(value))
return entry.getKey();
}
return -1L;
}
/**
* Returns <code>true</code> if the group option can be displayed if
* available, <code>false</code> otherwise.
*
* @return See above.
*/
private boolean hasGroupOption()
{
String usr = user.getText().trim();
String s = serverText.getText().trim();
return (usr.equals(originalName) && s.equals(originalServerName));
}
/**
* Brings up the server dialog to select an existing server or enter
* a new server address.
*/
private void config()
{
ServerDialog d;
String s = serverText.getText().trim();
if (connectionSpeed)
d = new ServerDialog(this, editor, s, speedIndex);
else d = new ServerDialog(this, editor, s);
if (editor.getRowCount() == 0 && configureServerName != null)
editor.addRow(configureServerName);
d.addPropertyChangeListener(this);
UIUtilities.centerAndShow(d);
}
/**
* Sets the {@link #encrypted} flag and modifies the icon of the
* {@link #encryptedButton} accordingly.
*/
private void encrypt()
{
if (!encryptedButton.isEnabled()) return;
encrypted = !encrypted;
IconManager icons = IconManager.getInstance();
if (encrypted)
encryptedButton.setIcon(icons.getIcon(IconManager.ENCRYPTED_24));
else encryptedButton.setIcon(icons.getIcon(IconManager.DECRYPTED_24));
}
/** Adds listeners to the UI components. */
private void initListeners()
{
user.getDocument().addDocumentListener(this);
pass.getDocument().addDocumentListener(this);
login.addActionListener(this);
user.addActionListener(this);
pass.addActionListener(this);
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { quit(); }
});
configButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { config(); }
});
encryptionListener = new ActionListener() {
public void actionPerformed(ActionEvent e) { encrypt(); }
};
encryptedButton.addActionListener(encryptionListener);
addWindowListener(new WindowAdapter()
{
public void windowOpened(WindowEvent e) {
requestFocusOnField();
}
});
user.addMouseListener(new MouseAdapter() {
/**
* Fires a property to move the window to the front.
* @see MouseListener#mouseClicked(MouseEvent)
*/
public void mouseClicked(MouseEvent e) {
firePropertyChange(TO_FRONT_PROPERTY, Boolean.valueOf(false),
Boolean.valueOf(true));
user.requestFocus();
//if (user.getText() != null)
// user.selectAll();
}
});
pass.addMouseListener(new MouseAdapter() {
/**
* Fires a property to move the window to the front.
* @see MouseListener#mouseClicked(MouseEvent)
*/
public void mouseClicked(MouseEvent e) {
firePropertyChange(TO_FRONT_PROPERTY, Boolean.valueOf(false),
Boolean.valueOf(true));
//requestFocusOnField();
}
});
}
/**
* Removes border and margin for the specified button and sets the default
* cursor to {@link Cursor#HAND_CURSOR}.
*
* @param button The button to set the default for.
*/
private void setButtonDefault(JButton button)
{
button.setRolloverEnabled(false);
button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
/** Initializes the groups.*/
private void initializeGroups()
{
groups = getGroups();
if (groups != null && groups.size() > 1) {
groupNames = new HashMap<Integer, String>();
groupValues = new String[groups.size()];
Entry<Long, String> entry;
Iterator<Entry<Long, String>> i = groups.entrySet().iterator();
int index = 0;
while (i.hasNext()) {
entry = i.next();
groupValues[index] = entry.getValue();
index++;
}
String selectedGroup = groupValues[groupValues.length-1];
//Review the groups
Arrays.sort(groupValues, new StringComparator());
String[] sorted = new String[groupValues.length];
String v;
String value;
for (int j = 0; j < groupValues.length; j++) {
v = groupValues[j];
value = v;
if (v.length() > MAX_CHAR) {
value = v.substring(0, MAX_CHAR)+"...";
}
groupNames.put(j, v);
sorted[j] = value;
if (selectedGroup.equals(v)) {
selectedGroup = value;
}
}
groupsBox = new JComboBox(sorted);
groupsBox.setSelectedItem(selectedGroup);
} else {
if (groupNames != null) groupNames.clear();
groupsBox = null;
}
}
/**
* Creates and initializes the components
*
* @param userName The name of the user.
* @param hostName The default hostName.
*/
private void initialize(String userName, String hostName)
{
components = new ArrayList<JComponent>();
//status update.
currentTask = new JLabel();
Font newFont = currentTask.getFont().deriveFont(8);
currentTask.setFont(newFont);
currentTask.setForeground(ScreenLogin.TEXT_COLOR);
progressBar = new JProgressBar();
progressBar.setVisible(false);
progressBar.setStringPainted(false);
progressBar.setFont(newFont);
originalName = userName;
user = new JTextField();
user.setName("username field");
user.setText(userName);
user.setToolTipText("Enter your username.");
user.setColumns(TEXT_COLUMN);
pass = new JPasswordField();
pass.setName("password field");
pass.setToolTipText("Enter your password.");
pass.setColumns(TEXT_COLUMN);
Map<String, String> servers = editor.getServers();
if (CommonsLangUtils.isNotBlank(hostName)) {
serverName = hostName;
//if user did point to another server
if (servers != null && servers.size() > 0) {
int n = servers.size()-1;
Iterator<String> i = servers.keySet().iterator();
int k = 0;
String value;
while (i.hasNext()) {
serverName = i.next();
if (k == n) {
value = servers.get(serverName);
if (value != null) {
try {
selectedPort = Integer.parseInt(value);
} catch (Exception e) {}
}
}
k++;
}
} else {
editor.removeLastRow();
editor.addRow(hostName);
}
} else {
if (servers == null || servers.size() == 0)
serverName = hostName;
else {
int n = servers.size()-1;
Iterator<String> i = servers.keySet().iterator();
int k = 0;
String value;
while (i.hasNext()) {
serverName = i.next();
if (k == n) {
value = servers.get(serverName);
if (value != null) {
try {
selectedPort = Integer.parseInt(value);
} catch (Exception e) {}
}
}
k++;
}
}
}
if (serverName.length() == 0) serverName = DEFAULT_SERVER;
if (!DEFAULT_SERVER.equals(serverName))
originalServerName = serverName;
connectionSpeedText = new JLabel(getConnectionSpeed());
connectionSpeedText.setForeground(TEXT_COLOR);
connectionSpeedText.setBorder(
BorderFactory.createEmptyBorder(5, 0, 0, 0));
serverText = UIUtilities.buildTextPane(serverName, TEXT_COLOR);
serverText.setName("server name text pane");
serverTextPane = UIUtilities.buildComponentPanelRight(serverText,
false);
serverTextPane.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
initializeGroups();
ref = new ArrayList<JComponent>();
login = new JButton("Login");
login.setName("login button");
defaultForeground = login.getForeground();
login.setMnemonic('L');
login.setToolTipText("Login");
setButtonDefault(login);
login.setEnabled(false);
//UIUtilities.enterPressesWhenFocused(login);
UIUtilities.opacityCheck(login);
cancel = new JButton("Quit");
cancel.setMnemonic('Q');
cancel.setToolTipText("Cancel Login.");
setButtonDefault(cancel);
UIUtilities.opacityCheck(cancel);
configButton = new JButton();
configButton.setName("config server button");
configButton.setMnemonic('X');
configButton.setToolTipText("Enter the server's address.");
configButton.setBorderPainted(false);
configButton.setBorder(null);
//configButton.setMargin(new Insets(1, 1, 1, 1));
configButton.setFocusPainted(false);
configButton.setContentAreaFilled(false);
IconManager icons = IconManager.getInstance();
configButton.setIcon(icons.getIcon(IconManager.CONFIG_24));
//configButton.setPressedIcon(icons.getIcon(
// IconManager.CONFIG_PRESSED_24));
encrypted = !isEncrypted();
encryptedButton = new JButton();
List<String> tips = new ArrayList<String>();
tips.add("The connection to the server is always encrypted.");
tips.add("If selected, the data transfer (e.g. annotations, images) " +
"will also be encrypted.");
tips.add("But the transfer will be much slower.");
encryptedButton.setToolTipText(UIUtilities.formatToolTipText(tips));
encryptedButton.setBorderPainted(false);
encryptedButton.setBorder(null);
encryptedButton.setFocusPainted(false);
encryptedButton.setContentAreaFilled(false);
if (encrypted)
encryptedButton.setIcon(icons.getIcon(IconManager.ENCRYPTED_24));
else encryptedButton.setIcon(icons.getIcon(IconManager.DECRYPTED_24));
getRootPane().setDefaultButton(login);
enableControls();
}
/**
* Layouts the groups or login options.
*
* @param group Pass <code>true</code> to display the groups options if
* available, <code>false</code> otherwise.
*/
private void layout(boolean group)
{
if (mainPanel == null) return;
if (ref == null) return;
Iterator<JComponent> i = ref.iterator();
boolean visible = false;
if (group) {
if (groups != null && groupsBox != null) visible = true;
}
while (i.hasNext()) {
i.next().setVisible(visible);
}
mainPanel.validate();
mainPanel.repaint();
}
/**
* Builds the UI component hosting the buttons.
*
* @return See above.
*/
private JPanel buildLogin()
{
//server information
JPanel p = new JPanel();
p.setOpaque(false);
p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
p.add(serverTextPane);
p.add(connectionSpeedText);
JToolBar bar = new JToolBar();
bar.setOpaque(false);
bar.setBorder(null);
bar.setFloatable(false);
if (UIUtilities.isWindowsOS()) {
bar.add(Box.createHorizontalStrut(5));
bar.add(encryptedButton);
bar.add(Box.createHorizontalStrut(5));
bar.add(configButton);
} else {
bar.add(encryptedButton);
bar.add(configButton);
}
JPanel row = new JPanel();
row.setOpaque(false);
row.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
row.add(p);
row.add(bar);
mainPanel.add(row);
components.add(row);
//user name
JPanel group = new JPanel();
group.setOpaque(false);
group.setLayout(new BoxLayout(group, BoxLayout.Y_AXIS));
JTextPane l = UIUtilities.buildTextPane(USER_TEXT, TEXT_COLOR);
row = new JPanel();
row.setOpaque(false);
row.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
row.add(l);
row.add(user);
group.add(row);
//password
l = UIUtilities.buildTextPane(" "+PASSWORD_TEXT, TEXT_COLOR);
row = new JPanel();
row.setOpaque(false);
row.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
row.add(l);
row.add(pass);
group.add(row);
mainPanel.add(group);
components.add(group);
//controls
JPanel controls = new JPanel();
controls.setOpaque(false);
controls.add(Box.createHorizontalGlue());
controls.add(login);
controls.add(cancel);
p = UIUtilities.buildComponentPanelCenter(controls, 0, 0, false);
mainPanel.add(p);
components.add(p);
return mainPanel;
}
/**
* Lays out the widgets and positions the window in the middle of
* the screen.
*
* @param logo The Frame's background logo.
* @param version The version of the software.
* @param serverAvailable Pass <code>true</code> if the client needs to
* connect to a server, <code>false</code> otherwise.
*/
private void buildGUI(Icon logo, String version, boolean serverAvailable)
{
JLabel splash = new JLabel(logo);
layers = new JLayeredPane();
layers.add(splash, Integer.valueOf(0));
getContentPane().add(layers);
int width = logo.getIconWidth();
int height = logo.getIconHeight();
layers.setBounds(0, 0, width, height);
splash.setBounds(0, 0, width, height);
int h = progressBar.getFontMetrics(progressBar.getFont()).getHeight();
int top = 120;
int bottom = 100;
currentTask.setBounds(TEXT_INDENT, top, width-2*TEXT_INDENT, h);
top += 20;
progressBar.setBounds(TEXT_INDENT, top, width-2*TEXT_INDENT, h);
addToLayer(currentTask);
addToLayer(progressBar);
mainPanel = new JPanel();
mainPanel.setOpaque(false);
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
Font f;
versionInfo = UIUtilities.buildTextPane(version, FOOT_NOTE_COLOR);
f = versionInfo.getFont();
versionInfo.setFont(f.deriveFont(VERSION_FONT_STYLE, f.getSize()-4));
versionInfo.setOpaque(false);
//Add login details.
int y = height-bottom-10;
y = top+2*h;
buildLogin();
displayComponents(serverAvailable);
mainPanel.add(UIUtilities.buildComponentPanelCenter(
versionInfo, 0, 0, false));
mainPanel.setBounds(0, y, width, height-top-bottom);
addToLayer(mainPanel);
}
/**
* Shows or hides the components.
*
* @param visible Pass <code>true</code> to show,
* <code>false</code> to hide.
*/
private void displayComponents(boolean visible)
{
Iterator<JComponent> i = components.iterator();
while (i.hasNext()) {
i.next().setVisible(visible);
}
repaint();
}
/**
* Returns the server's name.
*
* @return See above.
*/
private String getServerName()
{
String s = serverText.getText();
if (s == null) return null;
return s.trim();
}
/**
* Adds the connection speed to the passed string.
*
* @return The value of the connection speed.
*/
private String getConnectionSpeed()
{
switch (speedIndex) {
case LoginCredentials.HIGH: return " [LAN]";
case LoginCredentials.MEDIUM: return " [High]";
case LoginCredentials.LOW: return " [Low]";
}
return null;
}
/**
* Sets the value of the new server.
*
* @param s The value to set.
*/
private void setNewServer(String s)
{
if (CommonsLangUtils.isBlank(s)) {
if (configureServerName != null)
s = configureServerName;
else s = DEFAULT_SERVER;
}
String[] values = s.split(ServerEditor.SERVER_PORT_SEPARATOR, 0);
s = values[0];
if (values.length == 2) {
try {
selectedPort = Integer.parseInt(values[1]);
} catch (Exception e) {}
}
serverText.setText(s);
serverTextPane.validate();
serverTextPane.repaint();
initializeGroups();
layout(groupsBox != null);
enableControls();
}
/** Sets the enabled flag of the {@link #login} button.*/
private void enableControls()
{
boolean enabled = true;
String s = serverText.getText();
char[] name = pass.getPassword();
String usr = user.getText().trim();
if (CommonsLangUtils.isBlank(s) || CommonsLangUtils.isBlank(usr)) {
enabled = false;
} else {
s = s.trim();
if (DEFAULT_SERVER.equals(s)) {
enabled = false;
}
}
login.setEnabled(enabled);
if (enabled) {
ActionListener[] listeners = login.getActionListeners();
if (listeners != null) {
boolean set = false;
for (int i = 0; i < listeners.length; i++) {
if (listeners[i] == this) {
set = true;
break;
}
}
if (!set) login.addActionListener(this);
}
login.setForeground(defaultForeground);
} else {
login.setForeground(FOREGROUND_COLOR);
}
layout(hasGroupOption());
}
/**
* Sets the connection speed used to connect to the server.
*
* @param speed The connection speed.
*/
private void setConnectionSpeed(int speed)
{
speedIndex = speed;
Preferences prefs = Preferences.userNodeForPackage(ScreenLogin.class);
prefs.put(OMERO_CONNECTION_SPEED, ""+speedIndex);
}
/**
* Retrieves the connection speed used to connect to the server.
*
* @return See above.
*/
private int retrieveConnectionSpeed()
{
Preferences prefs = Preferences.userNodeForPackage(ScreenLogin.class);
String s = prefs.get(OMERO_CONNECTION_SPEED, null);
if (s == null || s.trim().length() == 0)
return LoginCredentials.HIGH;
return Integer.parseInt(s);
}
/**
* Sets the name of the user in the preferences.
*
* @param name The name to set.
*/
public void setUserName(String name)
{
if (name == null) return;
Preferences prefs = Preferences.userNodeForPackage(ScreenLogin.class);
prefs.put(OMERO_USER, name);
}
/**
* Returns the name of the user if saved.
*
* @return See above.
*/
private String getUserName()
{
Preferences prefs = Preferences.userNodeForPackage(ScreenLogin.class);
return prefs.get(OMERO_USER, null);
}
/**
* Returns <code>true</code> if the data transfer is encrypted,
* <code>false</code> otherwise.
*
* @return See above.
*/
private boolean isEncrypted()
{
Preferences prefs = Preferences.userNodeForPackage(ScreenLogin.class);
String value = prefs.get(OMERO_TRANSFER_ENCRYPTED, null);
return "true".equals(value);
}
/**
* Sets to <code>true</code> if the data transfer is encrypted,
* <code>false</code> otherwise.
*/
private void setEncrypted()
{
String value = "false";
if (encrypted) value = "true";
Preferences prefs = Preferences.userNodeForPackage(ScreenLogin.class);
prefs.put(OMERO_TRANSFER_ENCRYPTED, value);
}
/**
* Returns the possible groups.
*
* @return See above.
*/
private Map<Long, String> getGroups()
{
Map<Long, String> groups = new LinkedHashMap<Long, String>();
Preferences prefs = Preferences.userNodeForPackage(ScreenLogin.class);
String list = prefs.get(OMERO_USER_GROUP, null);
if (list == null || list.length() == 0) return groups;
String[] l = list.split(ServerEditor.SERVER_NAME_SEPARATOR, 0);
if (l == null) return groups;
int index;
String group;
String name;
long id;
String[] values;
String userName;
String serverName;
String selectedName = user.getText();
String selectedServer = serverText.getText();
for (index = 0; index < l.length; index++) {
group = l[index].trim();
if (group.length() > 0) {
values = group.split(ServerEditor.SERVER_PORT_SEPARATOR, 0);
if (values.length == 2) {
name = values[1];
try {
id = Long.parseLong(values[0]);
groups.put(id, name);
} catch (Exception e) {
//ignore: not possible to read the group
}
} else if (values.length == 4) {
userName = values[0];
serverName = values[1];
name = values[3];
if (userName.equals(selectedName) &&
serverName.equals(selectedServer)) {
try {
id = Long.parseLong(values[2]);
groups.put(id, name);
} catch (Exception e) {
//ignore: not possible to read the group
}
}
}
}
}
return groups;
}
/**
* Sets the default for the window.
*
* @param frameIcon The icon associated to the frame.
*/
private void setProperties(Image frameIcon)
{
setIconImage(frameIcon);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
setUndecorated(true);
toFront();
}
/**
* Creates a new instance.
*
* @param title The frame's title.
* @param logo The frame's background logo. Mustn't be <code>null</code>.
* @param frameIcon The image icon for the window.
* @param version The version of the software.
* @param defaultPort The default port.
* @param hostName The default host name.
* @param serverAvailable Pass <code>true</code> if the client needs to
* connect to a server, <code>false</code> otherwise.
*/
public ScreenLogin(String title, Icon logo, Image frameIcon, String version,
String defaultPort, String hostName, boolean serverAvailable)
{
super(title);
setName("login window");
selectedPort = -1;
Dimension d;
if (logo != null)
d = new Dimension(logo.getIconWidth(), logo.getIconHeight());
else d = DEFAULT_SIZE;
setSize(d);
setPreferredSize(d);
editor = new ServerEditor(defaultPort);
editor.addPropertyChangeListener(ServerEditor.REMOVE_PROPERTY, this);
speedIndex = retrieveConnectionSpeed();
initialize(getUserName(), hostName);
initListeners();
buildGUI(logo, version, serverAvailable);
encrypt();
setProperties(frameIcon);
showConnectionSpeed(false);
addMouseListener(new MouseAdapter() {
/**
* Fires a property to move the window to the front.
* @see MouseListener#mouseClicked(MouseEvent)
*/
public void mouseClicked(MouseEvent e) {
firePropertyChange(TO_FRONT_PROPERTY, Boolean.valueOf(false),
Boolean.valueOf(true));
requestFocusOnField();
}
});
}
/**
* Creates a new instance.
*
* @param title The frame's title.
* @param logo The frame's background logo.
* Mustn't be <code>null</code>.
* @param frameIcon The image icon for the window.
* @param version The version of the software.
* @param defaultPort The default port.
*/
public ScreenLogin(String title, Icon logo, Image frameIcon, String version,
String defaultPort)
{
this(title, logo, frameIcon, version, defaultPort, null, true);
}
/**
* Creates a new instance.
*
* @param title The frame's title.
* @param logo The frame's background logo.
* Mustn't be <code>null</code>.
* @param frameIcon The image icon for the window.
*/
public ScreenLogin(String title, Icon logo, Image frameIcon)
{
this(title, logo, frameIcon, null, null);
}
/**
* Creates a new instance.
*
* @param logo The frame's background logo.
* Mustn't be <code>null</code>.
* @param frameIcon The image icon for the window.
* @param version The version of the software.
*/
public ScreenLogin(Icon logo, Image frameIcon, String version)
{
this(null, logo, frameIcon, version, null);
}
/**
* Creates a new instance.
*
* @param logo The frame's background logo.
* Mustn't be <code>null</code>.
* @param frameIcon The image icon for the window.
*/
public ScreenLogin(Icon logo, Image frameIcon)
{
this(null, logo, frameIcon, null, null);
}
/**
* Indicates to show or hide the connection speed selection.
* By default the speed is hidden.
*
* @param connectionSpeed Pass <code>true</code> to show the
* connection speed option, <code>false</code>
* otherwise.
*/
public void showConnectionSpeed(boolean connectionSpeed)
{
this.connectionSpeed = connectionSpeed;
connectionSpeedText.setVisible(connectionSpeed);
}
/**
* Sets whether or not the buttons composing the display are enabled.
*
* @param b Pass <code>true</code> if this component should be enabled,
* <code>false</code> otherwise.
*/
public void setControlsEnabled(boolean b)
{
user.setEnabled(b);
pass.setEnabled(b);
login.setEnabled(b);
enableControls();
//login.requestFocus();
configButton.setEnabled(b);
encryptedButton.setEnabled(b);
if (groupsBox != null) groupsBox.setEnabled(b);
if (b) {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
setButtonDefault(login);
setButtonDefault(cancel);
} else {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
login.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
login.setEnabled(false);
}
}
/** Fails to log in. */
public void onLoginFailure()
{
loginAttempt = false;
setControlsEnabled(true);
displayComponents(true);
}
/** Sets the text of all textFields to <code>null</code>. */
public void cleanFields()
{
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
user.setText("");
pass.setText("");
}
/**
* Sets the text of the textField corresponding to the specified id
* to <code>null</code>.
*
* @param fieldID The textField's id. One of the following constants:
* {@link #USERNAME_FIELD} or {@link #PASSWORD_FIELD}.
*/
public void cleanField(int fieldID)
{
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
switch (fieldID) {
case USERNAME_FIELD:
user.setText("");
break;
case PASSWORD_FIELD:
pass.setText("");
break;
default:
cleanFields();
}
}
/** Closes and disposes. */
public void close()
{
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
setVisible(false);
dispose();
}
/**
* Sets the focus on the user name field if no user name entered
* otherwise, sets the focus on the password field.
*/
public void requestFocusOnField()
{
if (loginAttempt) return;
setControlsEnabled(true);
String txt = user.getText();
if (txt == null || txt.trim().length() == 0) user.requestFocus();
else pass.requestFocus();
}
public boolean hasAttemptedToLogin() { return loginAttempt; }
/**
* Sets the text of the {@link #cancel}.
*
* @param text The text to set.
*/
public void setQuitButtonText(String text)
{
if (text == null) return;
text = text.trim();
if (text.length() == 0) return;
if (text.equals(cancel.getText())) return;
cancel.setText(text);
char c = text.toUpperCase().charAt(0);
setQuitButtonMnemonic(c);
}
/**
* Sets the text displays when the cursor lingers over the component.
*
* @param toolTipText The text to set.
*/
public void setQuitButtonToolTipText(String toolTipText)
{
cancel.setToolTipText(toolTipText);
}
/**
* Sets the keyboard mnemonic.
*
* @param mnemonic The value to set.
*/
public void setQuitButtonMnemonic(int mnemonic)
{
cancel.setMnemonic(mnemonic);
}
/**
* Sets the total number of initialization tasks that have to be
* performed.
*
* @param maxTask The total number of tasks.
*/
public void initProgressBar(int maxTask)
{
progressBar.setMinimum(0);
progressBar.setMaximum(maxTask);
progressBar.setValue(0);
}
/**
* Adds the specified component to the layeredPane.
*
* @param c The component to add.
*/
public void addToLayer(JComponent c)
{
if (c == null) return;
layers.add(c, Integer.valueOf(1));
}
/**
* Sets the value of the progress bar and the status message.
*
* @param value The status message.
* @param perc The value to set.
*/
public void setStatus(String value, int perc)
{
currentTask.setText(value);
progressBar.setValue(perc);
}
/**
* Shows or hides the progress bar and the tasks label.
*
* @param visible Pass <code>true</code> to show, <code>false</code> to
* hide.
* @param requestFocus Pass <code>true</code> to request focus,
* <code>false</code> otherwise.
*/
public void setStatusVisible(boolean visible, boolean requestFocus)
{
currentTask.setVisible(visible);
progressBar.setVisible(visible);
if (requestFocus) {
login.setEnabled(true);
requestFocusOnField();
}
}
/**
* Sets the encryption parameters.
*
* @param encrypted Pass <code>true</code> to encrypt the data transfer,
* <code>false</code> otherwise.
* @param configurable Pass <code>true</code> to allow the user to interact
* with the encryption controls, <code>false</code> otherwise.
*/
public void setEncryptionConfiguration(boolean encrypted,
boolean configurable)
{
if ((encrypted && !this.encrypted) || (!encrypted && this.encrypted))
encrypt();
if (!configurable)
encryptedButton.removeActionListener(encryptionListener);
}
/**
* Indicates if the user can modify or not the host name from the UI.
*
* @param hostName The hostname.
* @param configurable Pass <code>true</code> to allow to change the
* host name, <code>false</code> otherwise.
* @param port The selected port.
*/
public void setHostNameConfiguration(String hostName, boolean configurable,
int port)
{
hostConfigurable = configurable;
configureServerName = hostName;
if (CommonsLangUtils.isNotBlank(hostName)) {
if (configurable) {
Map<String, String> servers = editor.getServers();
if (servers == null || servers.size() == 0)
editor.addRow(hostName);
else {
Iterator<String> i = servers.keySet().iterator();
String value;
boolean exist = false;
while (i.hasNext()) {
value = i.next();
if (hostName.equals(value)) {
exist = true;
break;
}
}
if (!exist) editor.addRow(hostName);
}
} else {
serverName = hostName;
originalServerName = serverName;
if (port < 0) {
selectedPort = Integer.parseInt(editor.getDefaultPort());
} else {
selectedPort = port;
}
setNewServer(originalServerName);
}
}
}
/**
* Indicates if the user can modify or not the host name from the UI.
*
* @param hostName The hostname.
* @param configurable Pass <code>true</code> to allow to change the
* host name, <code>false</code> otherwise.
*/
public void setHostNameConfiguration(String hostName, boolean configurable)
{
setHostNameConfiguration(hostName, configurable, -1);
}
/**
* Reacts to property changes fired by the <code>ScreenDialog</code>
* window.
* @see PropertyChangeListener#propertyChange(PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent evt)
{
String name = evt.getPropertyName();
if (ServerDialog.SERVER_PROPERTY.equals(name)) {
String v = getServerName();
String s = (String) evt.getNewValue();
if (s == null) {
setNewServer(null);
return;
}
String trim = s.trim();
if (v.equals(trim)) return;
setNewServer(trim);
} else if (ServerEditor.REMOVE_PROPERTY.equals(name)) {
requestFocusOnField();
String v = getServerName();
String oldValue = (String) evt.getOldValue();
if (v.equals(oldValue))
setNewServer((String) evt.getNewValue());
} else if (ServerDialog.CONNECTION_SPEED_PROPERTY.endsWith(name)) {
setConnectionSpeed(((Integer) evt.getNewValue()).intValue());
connectionSpeedText.setText(getConnectionSpeed());
}
}
/**
* Enables the controls.
* @see DocumentListener#insertUpdate(DocumentEvent)
*/
public void insertUpdate(DocumentEvent e) { enableControls(); }
/**
* Enables the controls.
* @see DocumentListener#removeUpdate(DocumentEvent)
*/
public void removeUpdate(DocumentEvent e) { enableControls(); }
/**
* Handles action events fired by the login fields and button.
* Once user name and password have been entered, the login fields and
* button will be disabled.
* @see ActionListener#actionPerformed(ActionEvent)
*/
public void actionPerformed(ActionEvent e) { login(); }
/**
* Required by the {@link DocumentListener} I/F but no-op implementation
* in our case.
* @see DocumentListener#changedUpdate(DocumentEvent)
*/
public void changedUpdate(DocumentEvent e) {}
}