/*******************************************************************************
* Copyright (c) 2006-2011 Gluster, Inc. <http://www.gluster.com>
* This file is part of Gluster Management Console.
*
* Gluster Management Console 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 3 of the License, or (at your option) any later version.
*
* Gluster Management Console 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, see
* <http://www.gnu.org/licenses/>.
*******************************************************************************/
package org.gluster.storage.management.console.dialogs;
import java.util.List;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.gluster.storage.management.console.Activator;
import org.gluster.storage.management.console.ConsoleConstants;
import org.gluster.storage.management.console.preferences.PreferenceConstants;
import org.gluster.storage.management.console.utils.GUIHelper;
/**
* Cluster selection dialog, which prompts for the cluster name to be managed
*/
public class ClusterSelectionDialog extends Dialog {
private static final String MESSAGE_SELECT_CLUSTER = "Select the Cluster you want to manage in this session.";
private static final String MESSAGE_CREATE_CLUSTER = "Create an empty Cluster and start adding servers to it.";
private static final String MESSAGE_REGISTER_CLUSTER = "Register an existing Cluster with the Management Gateway and start managing it using the Management Console.";
protected enum CLUSTER_MODE { SELECT, CREATE, REGISTER };
private Combo clusterNameCombo = null;
private Text newClusterNameText = null;
private Text existingClusterNameText = null;
private Text serverNameText = null;
private Button okButton;
private final GUIHelper guiHelper = GUIHelper.getInstance();
private Composite composite;
private ControlDecoration newClusterNameErrorDecoration;
private ControlDecoration existingClusterNameErrorDecoration;
private ControlDecoration serverNameErrorDecoration;
private List<String> clusters;
private Button selectButton;
private Button createButton;
private Button registerButton;
private Composite clusterSelectionComposite;
private Composite clusterCreationComposite;
private Composite clusterRegisterComposite;
private StackLayout stackLayout;
private String clusterName;
private CLUSTER_MODE clusterMode;
private String serverName;
private Button dontAskAgainButton;
IPreferenceStore preferenceStore;
public ClusterSelectionDialog(Shell parentShell, List<String> clusters) {
super(parentShell);
this.clusters = clusters;
preferenceStore = Activator.getDefault().getPreferenceStore();
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText("Gluster Management Console - Select Cluster");
addEscapeListener(newShell);
}
private void addEscapeListener(Shell shell) {
shell.addTraverseListener(new TraverseListener() {
@Override
public void keyTraversed(TraverseEvent e) {
if (e.keyCode == SWT.ESC) {
cancelPressed();
}
}
});
}
private void createClusterNameLabel(Composite composite) {
Label clusterNameLabel = new Label(composite, SWT.NONE);
clusterNameLabel.setText("Cluster &Name:");
clusterNameLabel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false));
}
private void createClusterNameCombo(Composite composite) {
clusterNameCombo = new Combo(composite, SWT.READ_ONLY);
clusterNameCombo.setItems(clusters.toArray(new String[0]));
clusterNameCombo.select(0);
String clusterName = preferenceStore.getString(PreferenceConstants.P_DEFAULT_CLUSTER_NAME);
if(clusterName != null && !clusterName.isEmpty()) {
selectCluster(clusterName);
}
}
public void selectCluster(String clusterName) {
for(int i = 0; i < clusters.size(); i++) {
if(clusterNameCombo.getItem(i).equals(clusterName)) {
clusterNameCombo.select(i);
break;
}
}
}
private void configureDialogLayout(Composite composite) {
GridLayout layout = (GridLayout) composite.getLayout();
layout.numColumns = 3;
layout.marginLeft = 20;
layout.marginRight = 20;
layout.marginTop = 20;
layout.horizontalSpacing = 20;
layout.verticalSpacing = 20;
}
/**
* Overriding to make sure that the dialog is centered in screen
*/
@Override
protected void initializeBounds() {
super.initializeBounds();
guiHelper.centerShellInScreen(getShell());
}
@Override
protected Control createDialogArea(Composite parent) {
//parent.setBackgroundImage(guiHelper.getImage(IImageKeys.DIALOG_SPLASH_IMAGE));
// Makes sure that child composites inherit the same background
parent.setBackgroundMode(SWT.INHERIT_FORCE);
composite = (Composite) super.createDialogArea(parent);
configureDialogLayout(composite);
createRadioButtons();
createSubComposites();
setupAutoSelectionIfRequired();
return composite;
}
private void setupAutoSelectionIfRequired() {
if (clusters.size() == 0) {
return;
}
final String clusterName = System.getProperty(ConsoleConstants.PROPERTY_AUTO_CLUSTER_NAME, null);
if (clusterName == null) {
return;
}
getShell().addShellListener(new ShellAdapter() {
@Override
public void shellActivated(ShellEvent e) {
super.shellActivated(e);
clusterNameCombo.setText(clusterName);
okPressed();
}
});
}
private void createSubComposites() {
Composite subComposite = new Composite(composite, SWT.NONE);
GridData data = new GridData();
data.horizontalSpan = 3;
subComposite.setLayoutData(data);
stackLayout = new StackLayout();
subComposite.setLayout(stackLayout);
createClusterSelectionComposite(subComposite, stackLayout);
createClusterCreationComposite(subComposite);
createClusterRegisterComposite(subComposite);
createRadioButtonListeners(subComposite);
if(clusters.size() > 0) {
selectButton.setSelection(true);
stackLayout.topControl = clusterSelectionComposite;
clusterNameCombo.setFocus();
} else {
createButton.setSelection(true);
stackLayout.topControl = clusterCreationComposite;
newClusterNameText.setFocus();
}
subComposite.layout();
}
private void createClusterRegisterComposite(Composite composite) {
clusterRegisterComposite = new Composite(composite, SWT.NONE);
GridLayout layout = new GridLayout(2, false);
layout.horizontalSpacing = 15;
clusterRegisterComposite.setLayout(layout);
createClusterNameLabel(clusterRegisterComposite);
existingClusterNameText = createText(clusterRegisterComposite);
existingClusterNameText.setToolTipText("Enter a name for the cluster being registered.");
existingClusterNameErrorDecoration = createErrorDecoration(existingClusterNameText, "Please enter a cluster name!");
existingClusterNameErrorDecoration.show();
createClusterServerLabel(clusterRegisterComposite);
serverNameText = createText(clusterRegisterComposite);
serverNameText.setToolTipText("Enter host name / IP address of one of the servers of the cluster.");
serverNameErrorDecoration = createErrorDecoration(serverNameText, "Please enter a server name!");
serverNameErrorDecoration.show();
}
private void createClusterServerLabel(Composite composite) {
Label serverNameLabel = new Label(composite, SWT.NONE);
serverNameLabel.setText("Server Na&me:");
serverNameLabel.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false));
}
private void createClusterCreationComposite(Composite subComposite) {
clusterCreationComposite = new Composite(subComposite, SWT.NONE);
GridLayout layout = new GridLayout(2, false);
layout.horizontalSpacing = 15;
clusterCreationComposite.setLayout(layout);
createClusterNameLabel(clusterCreationComposite);
newClusterNameText = createText(clusterCreationComposite);
newClusterNameText.setToolTipText("Enter name of the cluster to be created");
newClusterNameErrorDecoration = createErrorDecoration(newClusterNameText, "Please enter cluster name!");
newClusterNameErrorDecoration.show();
}
private Text createText(Composite parent) {
Text text = new Text(parent, SWT.NONE);
GridData layoutData = new GridData(SWT.FILL, GridData.FILL, true, false);
int width = convertWidthInCharsToPixels(32);
layoutData.widthHint = width;
layoutData.minimumWidth = width;
text.setLayoutData(layoutData);
text.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
validate();
}
});
return text;
}
private void createClusterSelectionComposite(Composite subComposite, StackLayout stackLayout) {
clusterSelectionComposite = new Composite(subComposite, SWT.NONE);
GridLayout layout = new GridLayout(2, false);
clusterSelectionComposite.setLayout(layout);
createClusterNameLabel(clusterSelectionComposite);
createClusterNameCombo(clusterSelectionComposite);
createPreferenceCheckbox(clusterSelectionComposite);
stackLayout.topControl = clusterSelectionComposite;
}
private void createPreferenceCheckbox(Composite composite) {
GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, false);
layoutData.verticalIndent = 5;
layoutData.horizontalSpan = 2;
dontAskAgainButton = new Button(composite, SWT.CHECK);
dontAskAgainButton.setLayoutData(layoutData);
dontAskAgainButton.setText("&Don't ask again");
dontAskAgainButton.setEnabled(true);
dontAskAgainButton.setSelection(false);
dontAskAgainButton.setToolTipText("Always manage the selected cluster without showing this dialog box."
+ "This preference can later be changed from the \"Settings\" menu.");
}
private void createRadioButtons() {
{
if (clusters.size() > 0) {
selectButton = new Button(composite, SWT.RADIO);
selectButton.setText("&Select");
selectButton.setToolTipText(MESSAGE_SELECT_CLUSTER);
}
}
{
createButton = new Button(composite, SWT.RADIO);
createButton.setText("&Create");
createButton.setToolTipText(MESSAGE_CREATE_CLUSTER);
}
{
registerButton = new Button(composite, SWT.RADIO);
registerButton.setText("&Register");
registerButton.setToolTipText(MESSAGE_REGISTER_CLUSTER);
}
}
private void validate() {
okButton.setEnabled(false);
if(selectButton != null && selectButton.getSelection()) {
okButton.setEnabled(true);
return;
}
if(createButton.getSelection()) {
String newClusterName = newClusterNameText.getText().trim();
if(newClusterName.isEmpty()) {
newClusterNameErrorDecoration.setDescriptionText("Please enter a cluster name!");
newClusterNameErrorDecoration.show();
} else if(clusters.contains(newClusterName)) {
newClusterNameErrorDecoration.setDescriptionText("Cluster [" + newClusterName + "] already exists!");
newClusterNameErrorDecoration.show();
} else {
okButton.setEnabled(true);
newClusterNameErrorDecoration.hide();
}
}
if(registerButton.getSelection()) {
okButton.setEnabled(true);
String clusterName = existingClusterNameText.getText().trim();
if(existingClusterNameText.getText().trim().isEmpty()) {
existingClusterNameErrorDecoration.setDescriptionText("Please enter a cluster name!");
existingClusterNameErrorDecoration.show();
okButton.setEnabled(false);
} else if(clusters.contains(clusterName)) {
existingClusterNameErrorDecoration.setDescriptionText("Cluster [" + clusterName + "] already exists!");
existingClusterNameErrorDecoration.show();
okButton.setEnabled(false);
} else {
existingClusterNameErrorDecoration.hide();
}
if(serverNameText.getText().trim().isEmpty()) {
serverNameErrorDecoration.show();
okButton.setEnabled(false);
} else {
serverNameErrorDecoration.hide();
}
}
}
private void createRadioButtonListeners(final Composite parent) {
if (clusters.size() > 0) {
selectButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
stackLayout.topControl = clusterSelectionComposite;
clusterNameCombo.select(0);
validate();
parent.layout();
clusterNameCombo.setFocus();
}
});
}
createButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
stackLayout.topControl = clusterCreationComposite;
validate();
parent.layout();
newClusterNameText.setFocus();
}
});
registerButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
stackLayout.topControl = clusterRegisterComposite;
validate();
parent.layout();
existingClusterNameText.setFocus();
}
});
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
setupDataBinding();
}
private ControlDecoration createErrorDecoration(Text text, String message) {
ControlDecoration errorDecoration = guiHelper.createErrorDecoration(text);
errorDecoration.setDescriptionText(message);
errorDecoration.hide();
return errorDecoration;
}
/**
* Sets up data binding between the text fields and the connection details object. Also attaches a "string required"
* validator to the "password" text field. This validator is configured to do the following on validation failure<br>
* <li>show an ERROR decorator</li><li>disable the "Login" button
*/
private void setupDataBinding() {
clusterNameCombo.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
if(clusterNameCombo.getText().trim().isEmpty()) {
okButton.setEnabled(false);
newClusterNameErrorDecoration.show();
} else {
okButton.setEnabled(true);
newClusterNameErrorDecoration.hide();
}
}
});
}
@Override
protected void okPressed() {
if(selectButton != null && selectButton.getSelection()) {
clusterMode = CLUSTER_MODE.SELECT;
clusterName = clusterNameCombo.getText();
if(dontAskAgainButton.getSelection()) {
preferenceStore.setValue(PreferenceConstants.P_SHOW_CLUSTER_SELECTION_DIALOG, false);
preferenceStore.setValue(PreferenceConstants.P_DEFAULT_CLUSTER_NAME, clusterName);
} else {
preferenceStore.setValue(PreferenceConstants.P_SHOW_CLUSTER_SELECTION_DIALOG, true);
}
} else if(createButton.getSelection()) {
clusterMode = CLUSTER_MODE.CREATE;
clusterName = newClusterNameText.getText().trim();
} else if(registerButton.getSelection()) {
clusterMode = CLUSTER_MODE.REGISTER;
clusterName = existingClusterNameText.getText().trim();
serverName = serverNameText.getText().trim();
}
super.okPressed();
}
public String getClusterName() {
return clusterName;
}
public CLUSTER_MODE getClusterMode() {
return clusterMode;
}
public String getServerName() {
return serverName;
}
}