/***********************************************************************
* Copyright (c) 2007 Anyware Technologies
*
* 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:
* Anyware Technologies - initial API and implementation
*
* $Id: FileChooser.java,v 1.1 2008/05/26 12:25:13 jlescot Exp $
**********************************************************************/
package org.eclipse.emf.ecoretools.tabbedproperties.sections.widgets;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecoretools.tabbedproperties.internal.utils.ColorRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
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.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.TypedListener;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory;
/**
*
* A field widget and a Button that allow you to retrieve an a file path from
* the filesystem<br>
*
* Creation : 3 avr. 07
*
* @author <a href="mailto:mickael.gerard@anyware-tech.com">Mickael Gerard</a>
*/
public class FileChooser extends Composite {
private Text field;
private Button chooseBt;
private TabbedPropertySheetWidgetFactory widgetFactory;
private String selectedFile;
/**
* Holds the fileChooserExtensionFilter
*/
private String[] filterExtensions;
/**
* Constructor
*
* @param parent
* the parent Composite
* @param factory
* the factory necessary to create the widget
* @param style
*/
public FileChooser(Composite parent, TabbedPropertySheetWidgetFactory factory, int style) {
super(parent, style);
this.widgetFactory = factory;
// default no filter
setFilterExtensions(new String[] { "*.*" }); //$NON-NLS-1$
createContents(this);
widgetFactory.adapt(this);
hookListeners();
}
/**
* Creates the UI. User must call the super method to create the main
* widgets (buttons) to this composite.
*
* @param parent
* this widget
*/
protected void createContents(Composite parent) {
setLayout(parent);
field = widgetFactory.createText(parent, "", SWT.FLAT | SWT.BORDER | SWT.READ_ONLY); //$NON-NLS-1$
field.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
chooseBt = widgetFactory.createButton(parent, "...", SWT.PUSH); //$NON-NLS-1$
}
/**
* This method sets a gridlayout to the composite. The number of columns is
* determined by the getNumberOfColumns method. The minimum number of
* columns is 2.
*
* @param parent
* the composite featuring a gridlayout
*/
private void setLayout(Composite parent) {
int numColumns = getNumberOfColumns();
if (numColumns < 2) {
numColumns = 2;
}
GridLayout layout = new GridLayout(numColumns, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
parent.setLayout(layout);
}
/**
* Returns the number of columns in this composite. The default object is 2
* because the main composite have 2 widgets.
*
* Returning a number less than 2 will be ingnored.
*
* @return The number of columns to set in this composite. It must be
* greater or equals than 2
*/
protected int getNumberOfColumns() {
return 2;
}
/**
* Adds the listeners on the choose button. If user overrides this method,
* he must call the super method to add the corresponding selection
* listener, otherwise disfunctions may occur
*/
protected void hookListeners() {
field.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
String oldPath = getSelection();
String newPath = field.getText();
if (newPath != null) {
newPath = newPath.trim();
}
setSelection(newPath, false);
handleFilePathChange(oldPath, newPath);
}
});
chooseBt.addSelectionListener(new SelectionAdapter() {
/**
* @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
handleChoose();
}
});
}
/**
* Sets the editable state of the text field. The default value is
* READ-ONLY. However clients may set this value as true by calling this
* method
*
* @param isEditable
*/
public void setEditable(boolean isEditable) {
if (field != null) {
field.setEditable(isEditable);
}
}
/**
* Open the dialog to choose in the searchable list
*/
private void handleChoose() {
FileDialog dialog = new FileDialog(getShell());
dialog.setFilterExtensions(getFilterExtensions());
String filePath = dialog.open();
if (filePath != null) {
String oldPath = getSelection();
setSelection(filePath);
handleFilePathChange(filePath, oldPath);
}
}
/**
* Notify listeners when filePath has changed
*
* @param filePath
* @param oldPath
*/
private void handleFilePathChange(String filePath, String oldPath) {
if (fileHasChanged(oldPath, filePath)) {
// to trigger handler on Modification
Event e = new Event();
notifyListeners(SWT.Modify, e);
}
}
/**
* Set whether the Choose button is enabled
*
* @param isChangeable
*/
public void setChangeable(boolean isChangeable) {
chooseBt.setEnabled(isChangeable);
}
/**
* Returns the selected object
*
* @return the selection
*/
public String getSelection() {
return selectedFile;
}
/**
* Set the selection of the comboViewer
*
* @param selection
* the selected object
*/
public void setSelection(String selection) {
setSelection(selection, true);
}
/**
* Set the selection of the FileChooser
*
* @param selection
* @param updateField
* boolean update text field if true
*/
public void setSelection(String selection, boolean updateField) {
String name = ""; //$NON-NLS-1$
if (selection != null) {
name = selection;
}
selectedFile = name;
if (updateField) {
field.setText(name);
if (field.isFocusControl()) {
field.setSelection(selectedFile.length());
}
}
}
/**
* Add a SelectionListener on the Button
*
* @param listener
*/
public void addModifyListener(ModifyListener listener) {
if (listener == null) {
SWT.error(SWT.ERROR_NULL_ARGUMENT);
}
TypedListener typedListener = new TypedListener(listener);
addListener(SWT.Modify, typedListener);
}
/**
* Remove the SelectionListener of the CCombo and the Button
*
* @param listener
*/
public void removeModifyListener(SelectionListener listener) {
if (listener == null) {
SWT.error(SWT.ERROR_NULL_ARGUMENT);
}
removeListener(SWT.Modify, listener);
}
/**
* @return the widgetFactory
*/
protected TabbedPropertySheetWidgetFactory getWidgetFactory() {
return widgetFactory;
}
/**
* Set the file extensions which the dialog will use to filter the files it
* shows to the argument, which may be null.
* <p>
* The strings are platform specific. For example, on Windows, an extension
* filter string is typically of the form "*.extension", where "*.*" matches
* all files.
* </p>
*
* @return String[]
*
* @see #setFilterExtensions to specify the user-friendly names
* corresponding to the extensions
*/
protected String[] getFilterExtensions() {
return filterExtensions;
}
/**
* @param filterExtensions
* String[]
*/
protected void setFilterExtensions(String[] filterExtensions) {
this.filterExtensions = filterExtensions;
}
/**
* Return true if newFilePath and oldFilePath are different
*
* @param oldFilePath
* @param newFilePath
* @return true if newFilePath and oldFilePath are different
*/
private boolean fileHasChanged(String oldFilePath, String newFilePath) {
boolean change = true;
if (oldFilePath == null && newFilePath == null || oldFilePath != null && oldFilePath.equals(newFilePath)) {
change = false;
}
return change;
}
/**
* Set widget status
*
* @param statusList
*/
public void setStatus(List<IStatus> statusList) {
if (statusList != null && !statusList.isEmpty()) {
int severity = -1;
String toolTip = ""; //$NON-NLS-1$
for (IStatus status : statusList) {
toolTip = "* " + status.getMessage() + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
if (severity != IStatus.ERROR) {
severity = status.getSeverity();
}
}
field.setToolTipText(toolTip.substring(0, toolTip.length() - 2));
if (severity == IStatus.ERROR) {
field.setBackground(ColorRegistry.COLOR_ERROR);
} else if (severity == IStatus.WARNING) {
field.setBackground(ColorRegistry.COLOR_WARNING);
}
} else {
field.setToolTipText(""); //$NON-NLS-1$
field.setBackground(ColorRegistry.COLOR_WHITE);
}
}
}