/*******************************************************************************
* Copyright (c) 2013 Arapiki Solutions Inc.
* 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:
* psmith - initial API and
* implementation and/or initial documentation
*******************************************************************************/
package com.buildml.eclipse.actions.dialogs;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import com.buildml.eclipse.utils.BmlTitleAreaDialog;
import com.buildml.model.IActionMgr;
import com.buildml.model.IActionTypeMgr;
import com.buildml.model.IBuildStore;
import com.buildml.model.ISlotTypes;
import com.buildml.model.ISlotTypes.SlotDetails;
/**
* A dialog allowing the user to select of an action's many slots. This is typically used for
* assigning file group (or other values) into slots.
*
* @author Peter Smith <psmith@arapiki.com>
*/
public class SlotSelectionDialog extends BmlTitleAreaDialog {
/*=====================================================================================*
* FIELDS/TYPES
*=====================================================================================*/
/** The buildStore's action manager */
private IActionMgr actionMgr;
/** The buildStore's action type manager */
private IActionTypeMgr actionTypeMgr;
/** The ID of the action we're querying */
private int actionId;
/** The ID of the slot that has been selected by the user */
private int slotId;
/** The name of the slot that has been selected by the user */
private String slotName;
/** The list box widget containing the "input" slot names */
private List inputSlotListBox;
/** The list box widget containing the "output" slot names */
private List outputSlotListBox;
/** All the input slot values */
private SlotDetails inputSlots[];
/** All the output slot values */
private SlotDetails outputSlots[];
/** Should the "input" slots be listed? */
private boolean showInputSlots;
/** Should the "output" slots be listed? */
private boolean showOutputSlots;
/*=====================================================================================*
* CONSTRUCTOR
*=====================================================================================*/
/**
* Create a new SlotSelectionDialog, used to allow the user to select one of the action's
* slots.
* @param buildStore The IBuildStore that contains the actions.
* @param actionId The ID of the action that owns the slots.
* @param showInputs Should the dialog show the "input" slots?
* @param showOutputs Should the dialog show the "output" slots?
*/
public SlotSelectionDialog(IBuildStore buildStore, int actionId,
boolean showInputs, boolean showOutputs) {
super(new Shell(), 0.3, 0.5, 0.5, 0.5);
this.actionMgr = buildStore.getActionMgr();
this.actionTypeMgr = buildStore.getActionTypeMgr();
this.actionId = actionId;
this.showInputSlots = showInputs;
this.showOutputSlots = showOutputs;
}
/*=====================================================================================*
* PUBLIC METHODS
*=====================================================================================*/
/**
* Return the ID of the selected slot. This should only be called after the "OK"
* button is pressed.
* @return the slotId
*/
public int getSlotId() {
return slotId;
}
/*-------------------------------------------------------------------------------------*/
/**
* Return the name of the selected slot. This should only be called after the "OK"
* button is pressed.
* @return the slotName
*/
public String getSlotName() {
return slotName;
}
/*=====================================================================================*
* PROTECTED METHODS
*=====================================================================================*/
/* (non-Javadoc)
* @see com.buildml.eclipse.utils.BmlTitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createDialogArea(Composite parent) {
/* what type is this action, and what is the type's name? */
int actionTypeId = actionMgr.getActionType(actionId);
if (actionTypeId < 0) {
setErrorMessage("Invalid action - can't display slots");
return parent;
}
String actionTypeName = actionTypeMgr.getName(actionTypeId);
if (actionTypeName == null) {
setErrorMessage("Invalid type of action - can't display slots");
return parent;
}
/* Create the main panel widget for the body of the dialog box */
Composite panel = new Composite(parent, SWT.NONE);
panel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
GridLayout layout = new GridLayout();
layout.marginHeight = 10;
layout.marginWidth = 20;
layout.verticalSpacing = 10;
layout.numColumns = 1;
panel.setLayout(layout);
/* Explanatory text that appears above the list */
Label label1 = new Label(panel, SWT.NONE);
label1.setText("Action Type: " + actionTypeName);
Label label2 = new Label(panel, SWT.NONE);
label2.setText("Select the Slot into which the selected File Group will be connected:");
TabFolder tabFolder = new TabFolder(panel, SWT.NONE);
tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
/*
* Prepare the list of "input" slots, if requested by the Dialog creator.
*/
if (showInputSlots) {
/* fetch the list of slots for this action type */
inputSlots = actionTypeMgr.getSlots(actionTypeId, ISlotTypes.SLOT_POS_INPUT);
if (inputSlots == null) {
setErrorMessage("Unable to retrieve \"input\" slot information for this action");
return parent;
}
/* add them to the listbox */
inputSlotListBox = addSlotsToListBox(tabFolder, "Input Slots", inputSlots);
}
/*
* Prepare the list of "output" slots, if requested by the Dialog creator.
*/
if (showOutputSlots) {
/* fetch the list of slots for this action type */
outputSlots = actionTypeMgr.getSlots(actionTypeId, ISlotTypes.SLOT_POS_OUTPUT);
if (outputSlots == null) {
setErrorMessage("Unable to retrieve \"output\" slot information for this action");
return parent;
}
/* add them to the listbox */
outputSlotListBox = addSlotsToListBox(tabFolder, "Output Slots", outputSlots);
}
return parent;
}
/*-------------------------------------------------------------------------------------*/
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.Dialog#okPressed()
*/
@Override
protected void okPressed() {
/*
* Determine which slot was highlighted - check the input list first, then the
* output list. At least one of the lists must have a selected item, otherwise
* "OK" would have been greyed out.
*/
int selectedIndex = -1;
/* an input slot was selected? */
if (showInputSlots) {
selectedIndex = inputSlotListBox.getSelectionIndex();
if (selectedIndex != -1) {
this.slotId = inputSlots[selectedIndex].slotId;
this.slotName = inputSlots[selectedIndex].slotName;
}
}
if (showOutputSlots && (selectedIndex == -1)) {
/* an output slot was selected? */
selectedIndex = outputSlotListBox.getSelectionIndex();
this.slotId = outputSlots[selectedIndex].slotId;
this.slotName = outputSlots[selectedIndex].slotName;
}
if (selectedIndex == -1) {
/* oops - button shouldn't have been enabled */
getButton(IDialogConstants.OK_ID).setEnabled(false);
return;
}
super.okPressed();
}
/*-------------------------------------------------------------------------------------*/
/*
* (non-Javadoc)
* @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
*/
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText("Connect to which slot?");
}
/*-------------------------------------------------------------------------------------*/
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.TrayDialog#createButtonBar(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createButtonBar(Composite parent) {
Control result = super.createButtonBar(parent);
/* until something is selected, the OK button is greyed out */
getButton(IDialogConstants.OK_ID).setEnabled(false);
return result;
}
/*=====================================================================================*
* PRIVATE METHODS
*=====================================================================================*/
/**
* Given an action type and a slot "position" add all the slot names to the tab, allowing
* the slot names to be selected.
*
* @param tabFolder The SWT TabFolder to add the tab to.
* @param tabTitle The text string to display at the top of the tab.
* @param slots The list of slots to be displayed.
* @return The newly added List widget (containing the slot names), or null on error.
*/
private List addSlotsToListBox(TabFolder tabFolder, String tabTitle, SlotDetails slots[]) {
/* create a new tab within the existing TabFolder */
TabItem slotTab = new TabItem(tabFolder, SWT.NONE);
slotTab.setText(tabTitle);
/* Add the list of slot names to the list box */
List listBox = new List(tabFolder, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
listBox.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
slotTab.setControl(listBox);
for (int i = 0; i != slots.length; i++) {
listBox.add(slots[i].slotName);
}
/*
* Make sure that selecting an item in this list will deselect all items in
* the other list. The only makes sense if both lists are shown.
*/
listBox.addSelectionListener(new SelectionListener() {
/* a slot was single-clicked */
@Override
public void widgetSelected(SelectionEvent e) {
/* deselect the other list box */
if (showInputSlots && showOutputSlots) {
if (e.getSource() == inputSlotListBox) {
outputSlotListBox.deselectAll();
} else {
inputSlotListBox.deselectAll();
}
}
/* it's now OK to press "OK" */
getButton(IDialogConstants.OK_ID).setEnabled(true);
}
/* a slot was double-clicked */
@Override
public void widgetDefaultSelected(SelectionEvent e) {
okPressed();
}
});
return listBox;
}
/*-------------------------------------------------------------------------------------*/
}