/******************************************************************************* * Copyright (c) 2011, 2014 Wind River Systems, Inc. and others. 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: * Wind River Systems - initial API and implementation *******************************************************************************/ package org.eclipse.tcf.te.ui.controls.file; import java.util.Arrays; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.dialogs.IDialogPage; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Dialog; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer; import org.eclipse.tcf.te.ui.controls.BaseDialogSelectionControl; import org.eclipse.tcf.te.ui.controls.nls.Messages; import org.eclipse.tcf.te.ui.controls.validator.FileNameValidator; import org.eclipse.tcf.te.ui.controls.validator.Validator; import org.eclipse.tcf.te.ui.interfaces.data.IDataExchangeNode; import org.osgi.framework.Bundle; /** * Base implementation of a simple file selection control. * <p> * The control supports direct editing by the user or browsing for the file. By * default, the control has a history of recently selected files. */ public class FileSelectionControl extends BaseDialogSelectionControl implements IDataExchangeNode { private String[] filterExtensions; private String[] filterNames; private String last_filter_path = null; /** * Constructor. * * @param parentPage The parent dialog page this control is embedded in. * Might be <code>null</code> if the control is not associated with a page. */ public FileSelectionControl(IDialogPage parentPage) { super(parentPage); setDialogTitle(Messages.FileSelectionControl_title_open); setGroupLabel(Messages.FileSelectionControl_group_label); setEditFieldLabel(Messages.FileSelectionControl_editfield_label); } /** * Set the filter extensions string array used by the standard file dialog. If set * to <code>null</code>, not filter extensions will be given to the file dialog. * * @param filterExtensions The filter extensions string array to use or <code>null</code>. */ public void setFilterExtensions(String[] filterExtensions) { this.filterExtensions = filterExtensions != null ? Arrays.copyOf(filterExtensions, filterExtensions.length) : null; if (getEditFieldValidator() != null && filterExtensions != null) { ((FileNameValidator)getEditFieldValidator()).setFileExtensions(filterExtensions); } } /** * Returns the filter extensions string array used by the standard file dialog. * * @return The filter extensions string array. */ public String[] getFilterExtensions() { return filterExtensions != null ? Arrays.copyOf(filterExtensions, filterExtensions.length) : new String[0]; } /** * Set the filter names string array used by the standard file dialog. If set * to <code>null</code>, not filter names will be given to the file dialog. * * @param filterExtensions The filter names string array to use or <code>null</code>. */ public void setFilterNames(String[] filterNames) { this.filterNames = filterNames != null ? Arrays.copyOf(filterNames, filterNames.length) : null; } /** * Returns the filter names string array used by the standard file dialog. * * @return The filter names string array or <code>null</code>. */ public String[] getFilterNames() { return filterNames != null ? Arrays.copyOf(filterNames, filterNames.length) : new String[0]; } /* (non-Javadoc) * @see org.eclipse.tcf.te.ui.controls.BaseDialogSelectionControl#doCreateDialogControl(org.eclipse.swt.widgets.Composite) */ @Override protected Dialog doCreateDialogControl(Composite parent) { Assert.isNotNull(parent); // create a standard file dialog FileDialog dialog = new FileDialog(parent.getShell(), SWT.OPEN); return dialog; } /* (non-Javadoc) * @see org.eclipse.tcf.te.ui.controls.BaseDialogSelectionControl#configureDialogControl(org.eclipse.swt.widgets.Dialog) */ @Override protected void configureDialogControl(Dialog dialog) { super.configureDialogControl(dialog); // we do expect a FileDialog here if (dialog instanceof FileDialog) { FileDialog fileDialog = (FileDialog)dialog; // set the file dialog filter extensions if available. if (getFilterExtensions().length > 0) { fileDialog.setFilterExtensions(getFilterExtensions()); } // set the file dialog filter names if available. if (getFilterNames().length > 0) { fileDialog.setFilterNames(getFilterNames()); } // the dialog should open within the directory of the currently selected // file. If no file has been currently selected, it should open within the // last browsed directory. String selectedFile = doGetSelectedFile(); if (selectedFile != null && selectedFile.trim().length() > 0) { IPath filePath = new Path(selectedFile); // If the selected file points to an directory, use the directory as is IPath filterPath = filePath.toFile().isDirectory() ? filePath : filePath.removeLastSegments(1); while (filterPath != null && filterPath.segmentCount() > 1 && !filterPath.toFile().exists()) { filterPath = filterPath.removeLastSegments(1); } String filterFileName = filePath.toFile().isDirectory() || !filePath.toFile().exists() ? null : filePath.lastSegment(); if (filterPath != null && !filterPath.isEmpty()) fileDialog.setFilterPath(filterPath.toString()); if (filterFileName != null) fileDialog.setFileName(filterFileName); } else { String filterPath = last_filter_path != null ? last_filter_path : doGetDefaultFilterPath(); fileDialog.setFilterPath(filterPath); } } } /* (non-Javadoc) * @see org.eclipse.tcf.te.ui.controls.BaseDialogSelectionControl#doApplyElementFromDialogControl(java.lang.String) */ @Override public void doApplyElementFromDialogControl(String selectedElement) { IPath path = selectedElement != null ? new Path(selectedElement) : null; super.doApplyElementFromDialogControl(path != null ? path.toOSString() : ""); //$NON-NLS-1$ } /** * Returns the file from which to set the initial directory. This method * is called from {@link #configureDialogControl(Dialog)} in case the dialog * is a {@link FileDialog}. * <p> * <b>Note:</b> The method may return a directory to use as initial directory * in case the selected file cannot be determined. * * @return The file to set the initial directory to the file dialog or <code>null</code> if none. */ protected String doGetSelectedFile() { String file = getEditFieldControlText(); return file.trim().length() > 0 ? file.trim() : null; } /** * Returns the default filter path to use if no file has been selected so far <b>and</b> * the dialog opens for the first time. * <p> * <b>Note:</b> The default implementation returns the current workspace location if the * resources plug-in is installed. * * @return The default filter path to use or <code>null</code>. */ protected String doGetDefaultFilterPath() { if (Platform.getBundle("org.eclipse.core.resources") != null //$NON-NLS-1$ && Platform.getBundle("org.eclipse.core.resources").getState() == Bundle.ACTIVE) { //$NON-NLS-1$ return org.eclipse.core.resources.ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString(); } return null; } /* (non-Javadoc) * @see org.eclipse.tcf.te.ui.controls.BaseEditBrowseTextControl#doCreateEditFieldValidator() */ @Override protected Validator doCreateEditFieldValidator() { return new FileNameValidator(Validator.ATTR_MANDATORY | FileNameValidator.ATTR_MUST_EXIST | FileNameValidator.ATTR_CAN_READ | FileNameValidator.ATTR_CAN_WRITE); } /* (non-Javadoc) * @see org.eclipse.tcf.te.ui.controls.BaseEditBrowseTextControl#configureEditFieldValidator(org.eclipse.tcf.te.ui.controls.validator.Validator) */ @Override protected void configureEditFieldValidator(Validator validator) { if (validator instanceof FileNameValidator) { if (getFilterExtensions() != null) { ((FileNameValidator)validator).setFileExtensions(getFilterExtensions()); } } } /* (non-Javadoc) * @see org.eclipse.tcf.te.ui.controls.BaseDialogSelectionControl#doOpenDialogControl(org.eclipse.swt.widgets.Dialog) */ @Override protected String doOpenDialogControl(Dialog dialog) { Assert.isNotNull(dialog); // We do expect a file dialog here. if (dialog instanceof FileDialog) { FileDialog fileDialog = (FileDialog)dialog; String selected = fileDialog.open(); if (selected != null) last_filter_path = fileDialog.getFilterPath(); return selected; } return null; } protected String getPropertiesKey() { return "File"; //$NON-NLS-1$ } /* (non-Javadoc) * @see org.eclipse.tcf.te.ui.interfaces.data.IDataExchangeNode#setupData(org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer) */ @Override public void setupData(IPropertiesContainer data) { doApplyElementFromDialogControl(data.getStringProperty(getPropertiesKey())); } /* (non-Javadoc) * @see org.eclipse.tcf.te.ui.interfaces.data.IDataExchangeNode#extractData(org.eclipse.tcf.te.runtime.interfaces.properties.IPropertiesContainer) */ @Override public void extractData(IPropertiesContainer data) { String file = doGetSelectedFile(); if (file != null && file.trim().length() > 0) { data.setProperty(getPropertiesKey(), new Path(file.trim()).toPortableString()); } else { data.setProperty(getPropertiesKey(), null); } } public boolean checkDataChanged(IPropertiesContainer data) { String file = doGetSelectedFile(); IPath path = new Path(file != null ? file : ""); //$NON-NLS-1$ String newValue = path.toPortableString(); if ("".equals(newValue)) { //$NON-NLS-1$ String oldValue = data.getStringProperty(getPropertiesKey()); return oldValue != null && !"".equals(oldValue.trim()); //$NON-NLS-1$ } return !data.isProperty(getPropertiesKey(), new Path(newValue).toPortableString()); } }