/*******************************************************************************
* Copyright (C) 2003-2006, 2013, Guillaume Brocker
* Copyright (C) 2015-2016, Andre Bossert
*
* 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:
* Guillaume Brocker - Initial API and implementation
* Andre Bossert - moved and improved dialog code to CustomDoxygenDialog
* - added support of eclipse variables to resolve doxygen path
*
******************************************************************************/
package eclox.core.ui;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import eclox.core.IPreferences;
import eclox.core.Plugin;
import eclox.core.doxygen.BundledDoxygen;
import eclox.core.doxygen.CustomDoxygen;
import eclox.core.doxygen.DefaultDoxygen;
import eclox.core.doxygen.Doxygen;
/**
* @author Guillaume Brocker
*/
public class DefaultDoxygenFieldEditor extends FieldEditor {
/**
* defines the version column index
*/
private final int VERSION_COLUMN_INDEX = 0;
/**
* defines the type column index
*/
private final int TYPE_COLUMN_INDEX = 1;
/**
* defines the description column index
*/
private final int DESCRIPTION_COLUMN_INDEX = 2;
/**
* the table control showing available doxygen wrappers
*/
private Table table;
/**
* the composite containing all buttons
*/
private Composite buttons;
/**
* the button that triggers the addition of a custom doxygen
*/
private Button add;
/**
* the button that triggers the edition of a custom doxygen
*/
private Button edit;
/**
* the button that triggers the removal of a custom doxygen
*/
private Button remove;
/**
* the valid state of the field editor
*/
private boolean valid = true;
/**
* Implements a selection listener for the owned table control.
*
* It is reponsible to ensure that only one table item is selected at a time
* and it also fires value change notifications.
*/
private class MySelectionListener implements SelectionListener {
/**
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected( e );
}
/**
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e) {
if (e.item instanceof TableItem ) onItemSelected( (TableItem) e.item );
else if (e.getSource() == add ) onAddSelected();
else if (e.getSource() == edit) onEditSelected();
else if (e.getSource() == remove) onRemoveSelected();
}
}
/**
* Adds a new table item for the given doxygen instance
*/
private void addItem( Doxygen doxygen ) {
TableItem item = new TableItem( table, 0 );
item.setData( doxygen );
updateItem( item );
}
/**
* Retrieves the type of the given doxygen wrapper instance
*/
private static String getDoxygenType( final Doxygen doxygen ) {
if ( doxygen instanceof DefaultDoxygen ) return "Default";
else if ( doxygen instanceof CustomDoxygen ) return "Custom";
else if ( doxygen instanceof BundledDoxygen ) return "Bundled";
else return "Uknown";
}
/**
* Updates the given table item.
*/
private void updateItem( TableItem item ) {
// Item data preparation.
final Doxygen doxygen = (Doxygen) item.getData();
final String type = getDoxygenType( doxygen );
final String version = doxygen.getVersion();
final String description = doxygen.getDescription();
// Updates the item properties.
item.setImage( (version == null) ? PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_WARN_TSK) : null );
item.setText( VERSION_COLUMN_INDEX, (version == null) ? "unknown" : version );
item.setText( TYPE_COLUMN_INDEX, type );
item.setText( DESCRIPTION_COLUMN_INDEX, description );
// Updates the table layout.
table.getColumn( VERSION_COLUMN_INDEX ).pack();
table.getColumn( TYPE_COLUMN_INDEX ).pack();
table.getColumn( DESCRIPTION_COLUMN_INDEX ).pack();
table.layout();
}
/**
* Checkes the table item representing the given doxygen identifier.
*/
private void checkItem( final String identifier ) {
TableItem[] items = table.getItems();
for( int i = 0; i < items.length; ++i ) {
Doxygen current = (Doxygen) items[i].getData();
items[i].setChecked( current.getIdentifier().equalsIgnoreCase( identifier ) );
}
}
/**
* Retrieves checked items.
*
* @return the checked item or null if none
*/
private TableItem[] getCheckedItems() {
// Pre-condition
assert( table != null );
Vector<TableItem> checked = new Vector<TableItem>();
TableItem[] items = table.getItems();
for( int i = 0; i < items.length; ++i ) {
if( items[i].getChecked() == true ) {
checked.add( items[i] );
}
}
return (TableItem[]) checked.toArray( new TableItem[0] );
}
/**
* Process the click on the add button.
*/
private void onAddSelected() {
// Asks the user to select a location containing a doxygen binary.
CustomDoxygenDialog dialog = new CustomDoxygenDialog(getPage().getShell(), null);
dialog.open();
String directory = dialog.getTargetDirectory();
if( directory != null ) {
addItem( new CustomDoxygen(directory) );
}
}
/**
* Process the click on the edit button
*/
private void onEditSelected() {
// Pre-condition
assert( table != null );
// Retrieves the checked items
TableItem[] selected = table.getSelection();
// Retrieves the doxygen wrapper associated to the selected item
assert( selected.length == 1 );
Doxygen doxygen = (Doxygen) selected[0].getData();
// Asks the user to select a location containing a doxygen binary.
assert( doxygen instanceof CustomDoxygen );
CustomDoxygen customDoxygen = (CustomDoxygen) doxygen;
CustomDoxygenDialog dialog = new CustomDoxygenDialog(getPage().getShell(), customDoxygen.getLocation());
dialog.open();
String directory = dialog.getTargetDirectory();
if( directory != null ) {
customDoxygen.setLocation( directory );
updateItem( selected[0] );
}
}
/**
* Process the click on the remove button
*/
private void onRemoveSelected() {
// Pre-condition
assert( table != null );
table.remove( table.getSelectionIndex() );
refreshValidState();
}
/**
* Process the selection of the given table item.
*/
private void onItemSelected( TableItem item ) {
if( item.getChecked() == true ) {
TableItem[] checked = getCheckedItems();
// Updates checked items so that only one is checked at the same time.
for( int i = 0; i < checked.length; ++i ) {
if( checked[i] != item ) {
checked[i].setChecked( false );
}
}
// Selects the item that has been checked.
table.setSelection( table.indexOf(item) );
// TODO only supported in eclipse 3.2
// table.setSelection( item );
// Fires some notifications.
fireValueChanged( VALUE, null, null );
}
// Updates button states
final boolean enable = item.getData() instanceof CustomDoxygen;
edit.setEnabled( enable );
remove.setEnabled( enable );
// Refreshes the field validity.
refreshValidState();
}
/**
* @see org.eclipse.jface.preference.FieldEditor#adjustForNumColumns(int)
*/
protected void adjustForNumColumns(int numColumns) {
// Pre-condition
assert( table != null );
GridData tableData = (GridData) table.getLayoutData();
GridData buttonsData = (GridData) buttons.getLayoutData();
tableData.horizontalSpan = numColumns - 1;
buttonsData.horizontalSpan = 1;
}
/**
* @see org.eclipse.jface.preference.FieldEditor#doFillIntoGrid(org.eclipse.swt.widgets.Composite, int)
*/
protected void doFillIntoGrid(Composite parent, int numColumns) {
// Pre-condition
assert( table == null );
// Creates the combo controls containing all available doxygen wrappers.
GridData tableData = new GridData( GridData.FILL_BOTH );
table = new Table( parent, SWT.SINGLE|SWT.CHECK|SWT.BORDER|SWT.FULL_SELECTION );
tableData.horizontalSpan = numColumns - 1;
table.setLayoutData( tableData );
table.addSelectionListener( new MySelectionListener() );
TableColumn versionColumn = new TableColumn( table, SWT.LEFT, VERSION_COLUMN_INDEX );
TableColumn typeColumn = new TableColumn( table, SWT.LEFT, TYPE_COLUMN_INDEX );
TableColumn descriptionColumn = new TableColumn( table, SWT.LEFT, DESCRIPTION_COLUMN_INDEX );
versionColumn.setText( "Version" );
typeColumn.setText( "Type" );
descriptionColumn.setText( "Description" );
table.setHeaderVisible( true );
// Creates the composite containing all buttons and located on the right side of the table.
GridData buttonsData = new GridData( GridData.END );
FillLayout buttonsLayout = new FillLayout( SWT.VERTICAL );
buttons = new Composite( parent, SWT.NO_FOCUS );
buttonsData.horizontalSpan = 1;
buttonsData.horizontalAlignment = SWT.FILL;
buttons.setLayoutData( buttonsData );
buttonsLayout.spacing = 5;
buttons.setLayout( buttonsLayout );
// Creates the button controlling custom doyxgen wrappers.
add = new Button( buttons, SWT.PUSH );
edit = new Button( buttons, SWT.PUSH );
remove = new Button( buttons, SWT.PUSH );
add.setText( "Add..." );
add.addSelectionListener( new MySelectionListener() );
edit.setText( "Edit..." );
edit.addSelectionListener( new MySelectionListener() );
edit.setEnabled( false );
remove.setText( "Remove" );
remove.addSelectionListener( new MySelectionListener() );
remove.setEnabled( false );
}
/**
* @see org.eclipse.jface.preference.FieldEditor#doLoad()
*/
protected void doLoad() {
// Adds default doxygen instance.
addItem( new DefaultDoxygen() );
// Adds custom doxygens.
final String raw = getPreferenceStore().getString(IPreferences.CUSTOM_DOXYGENS);
final String[] splitted = raw.split("\n");
for( int i = 0; i < splitted.length; ++i ) {
Doxygen doxygen = Doxygen.getFromClassAndIdentifier(CustomDoxygen.class, splitted[i]);
if( doxygen != null ) {
addItem( doxygen );
}
else {
Plugin.getDefault().logError( splitted[i] + ": invalid custom doxygen identifier found." );
}
}
// Adds bundled doxygens.
Collection<?> bundled = BundledDoxygen.getAll();
Iterator<?> i = bundled.iterator();
while( i.hasNext() ) {
addItem( (Doxygen) i.next() );
}
// Select the default doxygen wrapper
checkItem( getPreferenceStore().getString( IPreferences.DEFAULT_DOXYGEN ) );
}
/**
* @see org.eclipse.jface.preference.FieldEditor#doLoadDefault()
*/
protected void doLoadDefault() {
// Adds default doxygen instance.
addItem( new DefaultDoxygen() );
// Select the default doxygen wrapper
checkItem( getPreferenceStore().getDefaultString( IPreferences.DEFAULT_DOXYGEN ) );
}
/**
* @see org.eclipse.jface.preference.FieldEditor#doStore()
*/
protected void doStore() {
// Pre-condition
assert( table != null );
// Saves all custom doxygen wrappers.
TableItem[] items = table.getItems();
String serialized = new String();
for( int i = 0; i < items.length; ++i ) {
Object itemData = items[i].getData();
if( itemData instanceof CustomDoxygen ) {
CustomDoxygen doxygen = (CustomDoxygen) itemData;
serialized = serialized.concat( doxygen.getIdentifier() );
serialized = serialized.concat( "\n" );
}
}
getPreferenceStore().setValue( IPreferences.CUSTOM_DOXYGENS, serialized );
// Saves the checked item.
TableItem[] checked = getCheckedItems();
String defaultDoxygen = new String();
if( checked.length == 1 ) {
Doxygen doxygen = (Doxygen) checked[0].getData();
defaultDoxygen = doxygen.getIdentifier();
}
getPreferenceStore().setValue( IPreferences.DEFAULT_DOXYGEN, defaultDoxygen );
}
/**
* @see org.eclipse.jface.preference.FieldEditor#refreshValidState()
*/
protected void refreshValidState() {
TableItem[] checked = getCheckedItems();
boolean oldValid = valid;
boolean newValid = checked.length == 1;
// Updates validity and error message.
valid = newValid;
if( valid == false ) {
showErrorMessage( "Select the doxygen version to use." );
}
else {
clearErrorMessage();
}
// Send some notifications.
if( newValid != oldValid ) {
fireStateChanged( IS_VALID, oldValid, newValid );
}
}
/**
* Constructor
*/
public DefaultDoxygenFieldEditor( Composite parent ) {
super( IPreferences.DEFAULT_DOXYGEN, "Doxygen:", parent );
}
/**
* @see org.eclipse.jface.preference.FieldEditor#getNumberOfControls()
*/
public int getNumberOfControls() {
return 2;
}
/**
* @see org.eclipse.jface.preference.FieldEditor#isValid()
*/
public boolean isValid() {
return valid;
}
/**
* @see org.eclipse.jface.preference.FieldEditor#setFocus()
*/
public void setFocus() {
super.setFocus();
table.setFocus();
}
}