package org.nightlabs.jfire.reporting.ui.layout;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.jdo.JDOHelper;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.nightlabs.eclipse.ui.dialog.ResizableTrayDialog;
import org.nightlabs.jfire.reporting.layout.ReportRegistryItem;
import org.nightlabs.jfire.reporting.layout.id.ReportRegistryItemID;
/**
* A dialog that lets the user choose one or more items from an unfiltered
* {@link ReportRegistryItemTree}.
*
* @author Alexander Bieber <!-- alex [AT] nightlabs [DOT] de -->
*
*/
public class ReportRegistryItemDialog extends ResizableTrayDialog {
/**
* An instance of {@link ISelectionVerifier} can be set for a dialog and will be consulted when
* the selection changes in order to verify the selection for the use-case of the caller.
*/
public static interface ISelectionVerifier {
/**
* Will be called when the selection in the tree changes and returns whether this selection
* is valid for the use-case of the implementation.
*
* @param reportRegistryItems The currently selected {@link ReportRegistryItem}s.
* @return Whether the given selection is valid.
*/
boolean isSelectionValid(Collection<ReportRegistryItem> reportRegistryItems);
}
private ReportRegistryItemTree layoutTree;
private Collection<ReportRegistryItemID> selectedItemIDs;
private ISelectionVerifier selectionVerifier;
/**
* Create a new {@link ReportRegistryItemDialog} with the given Shell as parent.
*
* @param parentShell The parent Shell for the new dialog.
* @param selectionVerifier A {@link ISelectionVerifier} that is asked whether the current
* selection can be passed as result. This can be <code>null</code>, in this case
* every selection is valid.
*/
public ReportRegistryItemDialog(Shell parentShell, ISelectionVerifier selectionVerifier) {
super(parentShell, null);
this.selectionVerifier = selectionVerifier;
}
/**
* {@inheritDoc}
*/
@Override
protected Control createDialogArea(Composite parent) {
layoutTree = new ReportRegistryItemTree(parent, false, null);
layoutTree.getTreeViewer().addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
Set<ReportRegistryItem> selectedElements = layoutTree.getSelectedElements();
if (selectionVerifier != null && selectionVerifier.isSelectionValid(selectedElements)) {
Collection<ReportRegistryItemID> selectedIDs = new HashSet<ReportRegistryItemID>();
for (ReportRegistryItem item : selectedElements) {
selectedIDs.add((ReportRegistryItemID) JDOHelper.getObjectId(item));
}
selectedItemIDs = selectedIDs;
} else {
selectedItemIDs = null;
}
updateOKButton();
}
});
layoutTree.getTreeViewer().addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
if (selectedItemIDs != null)
close();
}
});
layoutTree.getTreeViewer().expandToLevel(3);
return layoutTree;
}
/**
* Updates the OK Button to be only enabled when the selection was valid.
*/
private void updateOKButton() {
Button okButton = getButton(IDialogConstants.OK_ID);
if (okButton != null) {
okButton.setEnabled(selectedItemIDs != null);
}
}
/**
* {@inheritDoc}
*/
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText("Select report layout");
}
/**
* @return The ID-Objects of the {@link ReportRegistryItem}s that were the last valid selection
* in this dialog, or <code>null</code> if the last selection was not valid.
*/
public Collection<ReportRegistryItemID> getSelectedItemIDs() {
return selectedItemIDs;
}
/**
* Opens a {@link ReportRegistryItemDialog} with the given shell as parent and returns the last
* valid selection, or <code>null</code> if the user cancels the dialog.
*
* @param parentShell The parent Shell for the new dialog.
* @param selectionVerifier An {@link ISelectionVerifier} for the dialog, that checks the
* selection, or <code>null</code> if all selections are valid.
* @return The last valid selection in the dialog, or <code>null</code> if the user cancels the
* dialog.
*/
public static Collection<ReportRegistryItemID> openDialog(Shell parentShell, ISelectionVerifier selectionVerifier) {
ReportRegistryItemDialog dlg = new ReportRegistryItemDialog(parentShell, selectionVerifier);
if (dlg.open() == Window.OK)
return dlg.getSelectedItemIDs();
return null;
}
/**
* Opens a {@link ReportRegistryItemDialog} with the given shell as parent and no
* {@link ISelectionVerifier} (i.e. all selections are valid regardless whether ReportCategory
* or ReportLayout).
*
* @param parentShell The parent Shell for the new dialog.
* @return The last valid selection in the dialog, or <code>null</code> if the user cancels the
* dialog.
*/
public static Collection<ReportRegistryItemID> openDialog(Shell parentShell) {
return openDialog(parentShell, null);
}
}