/* * Copyright (c) 2012 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * HUMBOLDT EU Integrated Project #030962 * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.ui.util.dialog; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.DialogTray; import org.eclipse.jface.dialogs.IDialogPage; import org.eclipse.jface.dialogs.IPageChangeProvider; import org.eclipse.jface.dialogs.IPageChangedListener; import org.eclipse.jface.dialogs.PageChangedEvent; import org.eclipse.jface.dialogs.TrayDialog; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ListViewer; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.FillLayout; 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.Display; import org.eclipse.swt.widgets.Shell; /** * Dialog consisting of multiple {@link IDialogPage}s * * @param <T> the dialog page type * * @author Simon Templer * @partner 01 / Fraunhofer Institute for Computer Graphics Research */ public abstract class MultiPageDialog<T extends IDialogPage> extends TrayDialog implements IPageChangeProvider { /** * Dialog page item */ private class PageItem { private final T page; /** * Creates a dialog page item * * @param page the dialog page */ public PageItem(T page) { this.page = page; } /** * @see Object#toString() */ @Override public String toString() { return page.getTitle(); } /** * @see Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + getOuterType().hashCode(); result = prime * result + ((page == null) ? 0 : page.hashCode()); return result; } /** * @see Object#equals(Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; @SuppressWarnings("unchecked") PageItem other = (PageItem) obj; if (!getOuterType().equals(other.getOuterType())) return false; if (page == null) { if (other.page != null) return false; } else if (!page.equals(other.page)) return false; return true; } private MultiPageDialog<T> getOuterType() { return MultiPageDialog.this; } } /** * Dialog tray */ private class PageTray extends DialogTray { private ListViewer viewer; /** * @see DialogTray#createContents(Composite) */ @Override protected Control createContents(Composite parent) { viewer = new ListViewer(parent); viewer.setContentProvider(new IStructuredContentProvider() { @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // ignore } @Override public void dispose() { // ignore } @SuppressWarnings("unchecked") @Override public Object[] getElements(Object inputElement) { try { List<T> pages = (List<T>) inputElement; List<PageItem> values = new ArrayList<PageItem>(); for (T page : pages) { values.add(new PageItem(page)); } return values.toArray(); } catch (Exception e) { return null; } } }); viewer.setInput(pages); updateSelection(); viewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { if (event.getSelection() instanceof IStructuredSelection) { IStructuredSelection selection = (IStructuredSelection) event .getSelection(); @SuppressWarnings("unchecked") PageItem item = (PageItem) selection.getFirstElement(); setCurrentPage(item.page); } } }); return parent; } /** * Update the selection in the viewer */ public void updateSelection() { if (viewer == null) return; T page = getCurrentPage(); if (page != null) { viewer.setSelection(new StructuredSelection(new PageItem(page))); } } } private final Set<IPageChangedListener> pageListeners = new HashSet<IPageChangedListener>(); private final List<T> pages = new ArrayList<T>(); private int currentIndex = 0; private final PageTray tray = new PageTray(); private String title; private Image image; private Composite pageArea; /** * Creates a new dialog using the current shell */ public MultiPageDialog() { this(Display.getCurrent().getActiveShell()); } /** * Creates a new dialog using the given shell * * @param shell the shell */ public MultiPageDialog(Shell shell) { super(shell); setShellStyle(getShellStyle() | SWT.SHELL_TRIM); } /** * @see Window#configureShell(Shell) */ @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(title); if (image != null) { newShell.setImage(image); } } /** * @see Dialog#createContents(Composite) */ @Override protected Control createContents(Composite parent) { Control c = super.createContents(parent); createPages(); Composite dialogArea = (Composite) getDialogArea(); if (pages.size() > 1) { GridLayout layout = new GridLayout(2, false); dialogArea.setLayout(layout); Composite trayControl = new Composite(dialogArea, SWT.NONE); GridData trayGrid = new GridData(SWT.FILL, SWT.FILL, false, true); trayControl.setLayoutData(trayGrid); trayControl.setLayout(new FillLayout()); tray.createContents(trayControl); pageArea = new Composite(dialogArea, SWT.NONE); GridData pageGrid = new GridData(SWT.FILL, SWT.FILL, true, true); pageArea.setLayoutData(pageGrid); pageArea.setLayout(new FillLayout()); // old - openTray(tray); } else { dialogArea.setLayout(new FillLayout()); this.pageArea = dialogArea; } updatePage(); return c; } /** * @see Dialog#getInitialSize() */ @Override protected Point getInitialSize() { return new Point(600, 400); } /** * Create the dialog pages and add them using the * {@link #addPage(IDialogPage)} method */ protected abstract void createPages(); /** * Adds a dialog page * * @param page the dialog page to add */ public void addPage(T page) { pages.add(page); } private void updatePage() { T page = getCurrentPage(); if (page != null) { page.createControl(pageArea); pageArea.layout(true); } } /** * @see IPageChangeProvider#addPageChangedListener(IPageChangedListener) */ @Override public void addPageChangedListener(IPageChangedListener listener) { pageListeners.add(listener); } /** * @see IPageChangeProvider#getSelectedPage() */ @Override public Object getSelectedPage() { return getCurrentPage(); } /** * Get the current page * * @return the current page */ public T getCurrentPage() { if (currentIndex < pages.size() && currentIndex >= 0) { return pages.get(currentIndex); } else { return null; } } private void setCurrentPage(T page) { T oldPage = getCurrentPage(); if (page == oldPage) return; if (allowPageChange(oldPage, page)) { int index = -1; int i = 0; Iterator<T> itPage = pages.iterator(); while (index < 0 && itPage.hasNext()) { T p = itPage.next(); if (p.equals(page)) { index = i; } i++; } if (index != currentIndex) { currentIndex = index; firePageChange(oldPage, page); oldPage.getControl().dispose(); updatePage(); } } else { tray.updateSelection(); } } /** * @see IPageChangeProvider#removePageChangedListener(IPageChangedListener) */ @Override public void removePageChangedListener(IPageChangedListener listener) { pageListeners.remove(listener); } /** * Fire a page change * * @param oldPage the old page * @param newPage the new page */ protected void firePageChange(T oldPage, T newPage) { onPageChange(oldPage, newPage); final PageChangedEvent pce = new PageChangedEvent(this, getSelectedPage()); for (IPageChangedListener listener : pageListeners) { listener.pageChanged(pce); } } /** * Called after the page has changed * * @param oldPage the old page * @param newPage the new page */ protected abstract void onPageChange(T oldPage, T newPage); /** * Called before the page changes * * @param oldPage the old page * @param newPage the new page * @return if the page change is allowed */ protected abstract boolean allowPageChange(T oldPage, T newPage); /** * @return the title */ public String getTitle() { return title; } /** * @param title the title to set */ public void setTitle(String title) { this.title = title; } /** * @return the image */ public Image getImage() { return image; } /** * @param image the image to set */ public void setImage(Image image) { this.image = image; } }