/* * Copyright (c) 2013 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: * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.ui.io.source; import java.io.File; import java.net.URI; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.jface.preference.FileFieldEditor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.PlatformUI; import eu.esdihumboldt.hale.ui.common.CommonSharedImages; import eu.esdihumboldt.hale.ui.service.project.RecentProjectsMenu; import eu.esdihumboldt.hale.ui.service.project.RecentResources; import eu.esdihumboldt.hale.ui.util.io.OpenFileFieldEditor; import eu.esdihumboldt.util.Pair; import eu.esdihumboldt.util.io.IOUtils; /** * A {@link OpenFileFieldEditor} with support for relative URIs with regard to * the current project's location. * * @author Kai Schwierczek * @author Simon Templer */ public class FileSourceFileFieldEditor extends OpenFileFieldEditor { private final URI projectURI; private boolean useRelative; private Button historyButton; /** * Default constructor. */ public FileSourceFileFieldEditor() { this(null); } /** * Constructor with the specified project URI. Can be used in conjunction * with {@link #setUseRelativeIfPossible(boolean)}. * * @param projectURI the project URI to use */ public FileSourceFileFieldEditor(URI projectURI) { super(); this.projectURI = projectURI; } /** * @see FileFieldEditor#FileFieldEditor(String, String, Composite) * @see #FileSourceFileFieldEditor(URI) */ @SuppressWarnings("javadoc") public FileSourceFileFieldEditor(String name, String labelText, Composite parent, URI projectURI) { super(name, labelText, parent); this.projectURI = projectURI; } /** * @see FileFieldEditor#FileFieldEditor(String, String, boolean, int, * Composite) * @see #FileSourceFileFieldEditor(URI) */ @SuppressWarnings("javadoc") public FileSourceFileFieldEditor(String name, String labelText, int validationStrategy, Composite parent, URI projectURI) { super(name, labelText, false, validationStrategy, parent); this.projectURI = projectURI; } /** * Sets the editor to allow relative values. The projectURI has to be * supplied during construction to support this feature. * * @param useRelative the new value */ public void setUseRelativeIfPossible(boolean useRelative) { if (this.useRelative && !useRelative) { File f = new File(getTextControl().getText()); f = resolve(f); if (f != null) getTextControl().setText(f.getAbsolutePath()); this.useRelative = false; } else if (!this.useRelative && useRelative && projectURI != null) { this.useRelative = true; File f = new File(getTextControl().getText()); URI absoluteSelected = f.toURI(); URI relativeSelected = IOUtils.getRelativePath(absoluteSelected, projectURI); if (!relativeSelected.isAbsolute()) f = new File(relativeSelected.toString()); getTextControl().setText(f.getPath()); } } /** * @see FileFieldEditor#changePressed() */ @Override protected String changePressed() { File f = new File(getTextControl().getText()); f = resolve(f); File d = getFile(f); return processFile(d); } /** * Process a selected file and produce the path to use. * * @param file the file * @return the path */ protected String processFile(File file) { if (file == null) { return null; } if (useRelative) { file = file.getAbsoluteFile(); URI absoluteSelected = file.toURI(); URI relativeSelected = IOUtils.getRelativePath(absoluteSelected, projectURI); if (!relativeSelected.isAbsolute()) file = new File(relativeSelected.toString()); } return file.getPath(); } @Override protected boolean checkState() { String msg = null; String path = getTextControl().getText(); if (path != null) { path = path.trim(); } else { path = "";//$NON-NLS-1$ } if (path.length() == 0) { if (!isEmptyStringAllowed()) { msg = getErrorMessage(); } } else { File file = resolve(new File(path)); if (file == null || !file.isFile()) { msg = getErrorMessage(); } } if (msg != null) { // error showErrorMessage(msg); return false; } if (doCheckState()) { // OK! clearErrorMessage(); return true; } msg = getErrorMessage(); // subclass might have changed it in the // #doCheckState() if (msg != null) { showErrorMessage(msg); } return false; } private File resolve(File f) { // first find absolute File resolved; if (f.isAbsolute()) resolved = f; else if (useRelative) resolved = new File(projectURI.resolve(IOUtils.relativeFileToURI(f))); else resolved = null; // then check existence if (resolved != null && resolved.exists()) return resolved; else return null; } // recent resources support @Override protected void adjustForNumColumns(int numColumns) { ((GridData) getTextControl().getLayoutData()).horizontalSpan = numColumns - 2; } @Override protected void doFillIntoGrid(Composite parent, int numColumns) { super.doFillIntoGrid(parent, numColumns - 1); } @Override public Text getTextControl(Composite parent) { // ensure resource control is added before the text control historyButton = new Button(parent, SWT.PUSH | SWT.FLAT); historyButton.setToolTipText("Choose from recent files"); historyButton.setImage( CommonSharedImages.getImageRegistry().get(CommonSharedImages.IMG_HISTORY)); historyButton.setEnabled(false); return super.getTextControl(parent); } @Override public void setContentTypes(Set<IContentType> types) { super.setContentTypes(types); RecentResources rr = PlatformUI.getWorkbench().getService(RecentResources.class); if (rr != null) { final List<Pair<URI, IContentType>> files = rr.getRecent(types, true); if (!files.isEmpty()) { historyButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Menu filesMenu = new Menu(historyButton); for (Pair<URI, IContentType> pair : files) { final File file; try { file = new File(pair.getFirst()); if (file.exists()) { // only offer existing files MenuItem item = new MenuItem(filesMenu, SWT.PUSH); item.setText(RecentProjectsMenu.shorten(file.toString(), 80, file.getName().length())); item.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { String text = processFile(file); if (text != null) { getTextControl().setText(text); getTextControl().setFocus(); valueChanged(); } } }); } } catch (Exception e1) { // ignore } } Point histLoc = historyButton.getParent() .toDisplay(historyButton.getLocation()); filesMenu.setLocation(histLoc.x, histLoc.y + historyButton.getSize().y); filesMenu.setVisible(true); } }); historyButton.setEnabled(true); } } } @Override public int getNumberOfControls() { return super.getNumberOfControls() + 1; } }