/******************************************************************************* * Copyright (c) 2011 Laurent CARON * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Laurent CARON (laurent.caron at gmail dot com) - initial API and implementation *******************************************************************************/ package org.mihalis.opal.login; import java.util.Arrays; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Path; import org.eclipse.swt.graphics.Pattern; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.mihalis.opal.opalDialog.Dialog; import org.mihalis.opal.utils.ResourceManager; import org.mihalis.opal.utils.SWTGraphicUtil; /** * Instances of this class are Login Dialog box, which is composed of * <p> * <dl> * <dt><b>A login</b></dt> * <dt><b>A password</b></dt> * <dt><b>An image</b></dt> * <dd>(optional)</dd> * <dt><b>A description</b></dt> * <dd>(optional)</dd> * <dt><b>A checkbox "remember the password"</b></dt> * <dd>(optional)</dd> * </dl> * </p> */ public class LoginDialog { private Image image; private String description; private String login; private String password; private List<String> autorizedLogin; private boolean displayRememberPassword; private boolean rememberPassword; private LoginDialogVerifier verifier; private Shell shell; private boolean returnedValue; private Button buttonOk; /** * Constructor */ public LoginDialog() { this.displayRememberPassword = true; } /** * Open the Login box * * @return <code>true</code> if the authentication is OK, <code>false</code> * if the user pressed on cancel. */ public boolean open() { if (this.verifier == null) { throw new IllegalArgumentException("Please set a verifier before opening the dialog box"); } buildDialog(); openShell(); return this.returnedValue; } /** * Build the dialog box */ private void buildDialog() { buildShell(); buildImage(); buildDescription(); buildLogin(); buildPassword(); if (this.displayRememberPassword) { buildRememberPassword(); } buildButtons(); } /** * Build the shell */ private void buildShell() { this.shell = new Shell(SWT.SYSTEM_MODAL | SWT.TITLE | SWT.BORDER); this.shell.setText(ResourceManager.getLabel(ResourceManager.LOGIN)); this.shell.setLayout(new GridLayout(4, false)); } /** * Build the image on top of the login box. If no image has been set, create * a default image */ private void buildImage() { final Canvas canvas = new Canvas(this.shell, SWT.DOUBLE_BUFFERED); final GridData gridData = new GridData(GridData.FILL, GridData.FILL, true, false, 4, 1); gridData.widthHint = 400; gridData.heightHint = 60; canvas.setLayoutData(gridData); canvas.addPaintListener(new PaintListener() { @Override public void paintControl(final PaintEvent e) { e.gc.drawImage(LoginDialog.this.image == null ? createDefaultImage(e.width, e.height) : LoginDialog.this.image, 0, 0); } }); } /** * Create a default image. It is a port of the image used by the Login Box * in the project SwingX * * @param w width * @param h height * @return a default image (blue wave) */ private Image createDefaultImage(final int w, final int h) { final Display display = Display.getCurrent(); final Color backgroundColor = new Color(display, 49, 121, 242); final Color gradientColor1 = new Color(display, 155, 185, 245); final Color gradientColor2 = new Color(display, 53, 123, 242); final Image img = new Image(display, w, h); final GC gc = new GC(img); gc.setAdvanced(true); gc.setAntialias(SWT.ON); gc.setBackground(backgroundColor); gc.fillRectangle(0, 0, w, h); final Path curveShape = new Path(display); curveShape.moveTo(0, h * .6f); curveShape.cubicTo(w * .167f, h * 1.2f, w * .667f, h * -.5f, w, h * .75f); curveShape.lineTo(w, h); curveShape.lineTo(0, h); curveShape.lineTo(0, h * .8f); curveShape.close(); final Pattern pattern = new Pattern(display, 0, 0, 1, h * 1.2f, gradientColor1, gradientColor2); gc.setBackgroundPattern(pattern); gc.fillPath(curveShape); final Font font = new Font(display, "Arial Bold", 30, SWT.NONE); gc.setFont(font); gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); final Point textSize = gc.stringExtent(ResourceManager.getLabel(ResourceManager.LOGIN)); gc.drawString(ResourceManager.getLabel(ResourceManager.LOGIN), (int) (w * .05f), (h - textSize.y) / 2, true); font.dispose(); curveShape.dispose(); pattern.dispose(); backgroundColor.dispose(); gradientColor1.dispose(); gradientColor2.dispose(); gc.dispose(); return img; } /** * Build the description part of the box */ private void buildDescription() { final Label label = new Label(this.shell, SWT.NONE); final GridData gridData = new GridData(GridData.FILL, GridData.BEGINNING, true, false, 4, 1); gridData.verticalIndent = 5; gridData.horizontalIndent = 5; label.setLayoutData(gridData); final Font bold = SWTGraphicUtil.buildFontFrom(label, SWT.BOLD); label.setFont(bold); SWTGraphicUtil.addDisposer(label, bold); if (this.description == null || this.description.trim().equals("")) { label.setText(" "); } else { label.setText(this.description); } } /** * Build the login part of the box */ private void buildLogin() { final Label label = new Label(this.shell, SWT.NONE); final GridData gridData = new GridData(GridData.END, GridData.END, false, false, 1, 1); gridData.horizontalIndent = 35; gridData.verticalIndent = 15; label.setLayoutData(gridData); label.setText(ResourceManager.getLabel(ResourceManager.NAME)); if (this.autorizedLogin != null && !this.autorizedLogin.isEmpty()) { // Combo buildLoginCombo(); } else { // Text buildLoginText(); } } private void buildLoginCombo() { final Combo combo = new Combo(this.shell, SWT.BORDER | SWT.READ_ONLY); combo.setLayoutData(new GridData(GridData.FILL, GridData.END, true, false, 3, 1)); for (final String loginToAdd : this.autorizedLogin) { combo.add(loginToAdd); } combo.setText(this.login == null ? "" : this.login); combo.setFocus(); combo.addModifyListener(new ModifyListener() { @Override public void modifyText(final ModifyEvent e) { LoginDialog.this.login = combo.getText(); changeButtonOkState(); } }); } private void buildLoginText() { final Text text = new Text(this.shell, SWT.BORDER); text.setText(this.login == null ? "" : this.login); text.setLayoutData(new GridData(GridData.FILL, GridData.END, true, false, 3, 1)); text.setFocus(); text.addModifyListener(new ModifyListener() { @Override public void modifyText(final ModifyEvent e) { LoginDialog.this.login = text.getText(); changeButtonOkState(); } }); } /** * Build the password part of the box */ private void buildPassword() { final Label label = new Label(this.shell, SWT.NONE); final GridData gridData = new GridData(GridData.END, GridData.CENTER, false, false, 1, 1); gridData.horizontalIndent = 35; label.setLayoutData(gridData); label.setText(ResourceManager.getLabel(ResourceManager.PASSWORD)); final Text text = new Text(this.shell, SWT.PASSWORD | SWT.BORDER); text.setText(this.password == null ? "" : this.password); text.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 3, 1)); text.addModifyListener(new ModifyListener() { @Override public void modifyText(final ModifyEvent e) { LoginDialog.this.password = text.getText(); changeButtonOkState(); } }); } /** * Enable/Disable the button when the login and the password is empty (or * not) */ private void changeButtonOkState() { final boolean loginEntered = this.login != null && !this.login.trim().equals(""); final boolean passwordEntered = this.password != null && !this.password.trim().equals(""); this.buttonOk.setEnabled(loginEntered && passwordEntered); } /** * Build the "remember password" part of the box */ private void buildRememberPassword() { final Button checkbox = new Button(this.shell, SWT.CHECK); final GridData gridData = new GridData(GridData.BEGINNING, GridData.CENTER, true, false, 4, 1); gridData.horizontalIndent = 35; checkbox.setLayoutData(gridData); checkbox.setText(ResourceManager.getLabel(ResourceManager.REMEMBER_PASSWORD)); checkbox.setSelection(this.rememberPassword); } /** * Build the buttons */ private void buildButtons() { buildOkButton(); buildCancelButton(); } private void buildOkButton() { this.buttonOk = new Button(this.shell, SWT.PUSH); final GridData gdOk = new GridData(GridData.END, GridData.CENTER, true, false, 3, 1); gdOk.verticalIndent = 60; gdOk.minimumWidth = 80; this.buttonOk.setLayoutData(gdOk); this.buttonOk.setText(ResourceManager.getLabel(ResourceManager.OK)); this.buttonOk.setEnabled(false); this.buttonOk.addSelectionListener(new SelectionAdapter() { /** * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected(final SelectionEvent selectionEvent) { try { LoginDialog.this.verifier.authenticate(LoginDialog.this.login, LoginDialog.this.password); LoginDialog.this.returnedValue = true; LoginDialog.this.shell.dispose(); } catch (final Exception e) { Dialog.error(ResourceManager.getLabel(ResourceManager.LOGIN_FAILED), e.getMessage()); for (final Control control : LoginDialog.this.shell.getChildren()) { if (control instanceof Text || control instanceof Combo) { control.setFocus(); break; } } } } }); } private void buildCancelButton() { final Button buttonCancel = new Button(this.shell, SWT.PUSH); final GridData gdCancel = new GridData(GridData.FILL, GridData.CENTER, false, false); gdCancel.widthHint = 80; gdCancel.verticalIndent = 60; buttonCancel.setLayoutData(gdCancel); buttonCancel.setText(ResourceManager.getLabel(ResourceManager.CANCEL)); buttonCancel.addSelectionListener(new SelectionAdapter() { /** * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected(final SelectionEvent e) { LoginDialog.this.returnedValue = false; LoginDialog.this.shell.dispose(); } }); } /** * Open the shell */ private void openShell() { this.shell.setDefaultButton(this.buttonOk); this.shell.pack(); this.shell.open(); SWTGraphicUtil.centerShell(this.shell); while (!this.shell.isDisposed()) { if (!this.shell.getDisplay().readAndDispatch()) { this.shell.getDisplay().sleep(); } } } // ------------- Getters & Setters /** * @return the image */ public Image getImage() { return this.image; } /** * @return the description */ public String getDescription() { return this.description; } /** * @return the login */ public String getLogin() { return this.login == null ? null : this.login.trim(); } /** * @return the password */ public String getPassword() { return this.password == null ? null : this.password.trim(); } /** * @return the list of autorized logins */ public List<String> getAutorizedLogin() { return this.autorizedLogin; } /** * @return <code>true</code> if the checkbox "remember the password" is * displayed, <code>false</code> otherwise */ public boolean isDisplayRememberPassword() { return this.displayRememberPassword; } /** * @return <code>true</code> if the checkbox "remember the password" is * checked, <code>false</code> otherwise */ public boolean isRememberPassword() { return this.rememberPassword; } /** * @return the verifier associated to this box */ public LoginDialogVerifier getVerifier() { return this.verifier; } /** * @param image the image to set */ public void setImage(final Image image) { this.image = image; } /** * @param description the description to set */ public void setDescription(final String description) { this.description = description; } /** * @param login the login to set */ public void setLogin(final String login) { this.login = login; } /** * @param password the password to set */ public void setPassword(final String password) { this.password = password; } /** * @param autorizedLogin the list of autorized logins to set */ public void setAutorizedLogin(final List<String> autorizedLogin) { this.autorizedLogin = autorizedLogin; } /** * @param autorizedLogin the list of autorized logins to set */ public void setAutorizedLogin(final String... autorizedLogin) { this.autorizedLogin = Arrays.asList(autorizedLogin); } /** * @param displayRememberPassword if <code>true</code>, the checkbox * "remember the password" is displayed */ public void setDisplayRememberPassword(final boolean displayRememberPassword) { this.displayRememberPassword = displayRememberPassword; } /** * @param rememberPassword if <code>true</code>, the checkbox * "remember the password" is selected */ public void setRememberPassword(final boolean rememberPassword) { this.rememberPassword = rememberPassword; } /** * @param verifier the verifier to set */ public void setVerifier(final LoginDialogVerifier verifier) { this.verifier = verifier; } }