package net.sourceforge.pmd.eclipse.ui.views;
import net.sourceforge.pmd.eclipse.ui.PMDUiConstants;
import net.sourceforge.pmd.eclipse.plugin.PMDPlugin;
import net.sourceforge.pmd.eclipse.ui.model.FileRecord;
import net.sourceforge.pmd.eclipse.ui.nls.StringKeys;
import net.sourceforge.pmd.eclipse.ui.views.actions.RemoveViolationAction;
import net.sourceforge.pmd.util.NumericConstants;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.IPage;
import org.eclipse.ui.part.Page;
/**
* Creates a Page for the Violation Outline
*
* @author SebastianRaffel ( 08.05.2005 )
*/
public class ViolationOutlinePage extends Page implements IPage, ISelectionChangedListener, RefreshableTablePage {
private TableViewer tableViewer;
private ViolationOutline violationOutline;
private ViewerFilter viewerFilter;
private FileRecord resource;
protected final Integer[] columnWidths = {Integer.valueOf(20), Integer.valueOf(170), Integer.valueOf(40)};
protected final int[] columnSortOrder = { 1, 1, 1 };
protected int currentSortedColumn;
/**
* Constructor
*
* @param resourceRecord, the FileRecord
* @param outline, the parent Outline
*/
public ViolationOutlinePage(FileRecord resourceRecord, ViolationOutline outline) {
resource = resourceRecord;
violationOutline = outline;
ViewerFilter[] filters = outline.getFilters();
for (int i = 0; i < filters.length; i++) {
if (filters[i] instanceof PriorityFilter)
viewerFilter = filters[i];
}
}
public TableViewer tableViewer() { return tableViewer; }
/* @see org.eclipse.ui.part.IPage#createControl(org.eclipse.swt.widgets.Composite) */
public void createControl(Composite parent) {
int tableStyle = SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION;
tableViewer = new TableViewer(parent, tableStyle);
tableViewer.setUseHashlookup(true);
tableViewer.getTable().setHeaderVisible(true);
// create the Table
createColumns(tableViewer.getTable());
createActionBars();
violationOutline.createContextMenu(tableViewer);
// set the Input
tableViewer.setContentProvider(new ViolationOutlineContentProvider(this));
tableViewer.setLabelProvider(new ViolationOutlineLabelProvider());
tableViewer.setInput(resource);
// add the Filter and Listener
tableViewer.addFilter(viewerFilter);
tableViewer.addSelectionChangedListener(this);
}
/**
* Create the Columns
*
* @param table
*/
private void createColumns(Table viewerTable) {
// Image for the Priority
final TableColumn priorityColumn = new TableColumn(viewerTable, SWT.LEFT);
priorityColumn.setWidth(20);
priorityColumn.setResizable(false);
// the Error-Message
final TableColumn messageColumn = new TableColumn(viewerTable, SWT.LEFT);
messageColumn.setWidth(170);
messageColumn.setText(getString(StringKeys.VIEW_OUTLINE_COLUMN_MESSAGE));
// the Line, the Error occurred
final TableColumn lineColumn = new TableColumn(viewerTable, SWT.RIGHT);
lineColumn.setWidth(40);
lineColumn.setText(getString(StringKeys.VIEW_OUTLINE_COLUMN_LINE));
createColumnAdapters(tableViewer.getTable());
tableViewer.setSorter(getViewerSorter(0));
}
/**
* Creates Adapter for sorting and resizing the Columns
*
* @param table
*/
private void createColumnAdapters(Table table) {
TableColumn[] columns = table.getColumns();
for (int k = 0; k < columns.length; k++) {
columnWidths[k] = Integer.valueOf(columns[k].getWidth());
final int i = k;
// the Sorter
columns[k].addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
currentSortedColumn = i;
columnSortOrder[currentSortedColumn] *= -1;
tableViewer.setSorter(getViewerSorter(currentSortedColumn));
}
});
// the Resizing
columns[k].addControlListener(new ControlAdapter() {
public void controlResized(ControlEvent e) {
columnWidths[i] = Integer.valueOf(tableViewer.getTable().getColumn(i).getWidth());
}
});
}
}
/**
* Creates the ActionBars
*/
private void createActionBars() {
IToolBarManager manager = getSite().getActionBars().getToolBarManager();
Action removeViolationAction = new RemoveViolationAction(tableViewer);
manager.add(removeViolationAction);
manager.add(new Separator());
}
/**
* Returns the ViewerSorter
*
* @param column, the Number of the Column
* @return, the Sorter for this Column
*/
private ViewerSorter getViewerSorter(int columnNr) {
TableColumn column = tableViewer.getTable().getColumn(columnNr);
final int sortOrder = columnSortOrder[columnNr];
switch (columnNr) {
// sorts by the Priority
case 0:
return new TableColumnSorter(column, sortOrder) {
public int compare(Viewer viewer, Object e1, Object e2) {
IMarker marker1 = (IMarker) e1;
IMarker marker2 = (IMarker) e2;
Integer prio1 = NumericConstants.ZERO;
Integer prio2 = NumericConstants.ZERO;
try {
prio1 = (Integer) marker1.getAttribute(PMDUiConstants.KEY_MARKERATT_PRIORITY);
prio2 = (Integer) marker2.getAttribute(PMDUiConstants.KEY_MARKERATT_PRIORITY);
if (prio1.equals(prio2)) {
prio1 = (Integer) marker1.getAttribute(IMarker.LINE_NUMBER);
prio2 = (Integer) marker2.getAttribute(IMarker.LINE_NUMBER);
}
} catch (CoreException ce) {
PMDPlugin.getDefault().logError(StringKeys.ERROR_CORE_EXCEPTION, ce);
}
return prio1 == null ? 0 : prio1.compareTo(prio2) * sortOrder;
}
};
// sorts by the Message
case 1:
return new TableColumnSorter(column, sortOrder) {
public int compare(Viewer viewer, Object e1, Object e2) {
String message1 = "";
String message2 = "";
try {
message1 = String.valueOf(((IMarker) e1).getAttribute(IMarker.MESSAGE));
message2 = String.valueOf(((IMarker) e2).getAttribute(IMarker.MESSAGE));
} catch (CoreException ce) {
PMDPlugin.getDefault().logError(StringKeys.ERROR_CORE_EXCEPTION + this.toString(), ce);
}
return message1 == null ? 0 : message1.compareTo(message2) * sortOrder;
}
};
// sorts by the Line-Number
case 2:
return new TableColumnSorter(column, sortOrder) {
public int compare(Viewer viewer, Object e1, Object e2) {
Integer prio1;
Integer prio2;
try {
prio1 = (Integer) ((IMarker) e1).getAttribute(IMarker.LINE_NUMBER);
prio2 = (Integer) ((IMarker) e2).getAttribute(IMarker.LINE_NUMBER);
return prio1 == null ? 0 : prio1.compareTo(prio2) * sortOrder;
} catch (CoreException ce) {
ce.printStackTrace();
}
return 0;
}
};
}
return null;
}
/**
* @return the Viewer
*/
public TableViewer getTableViewer() {
return tableViewer;
}
/* @see org.eclipse.ui.part.IPage#getControl() */
public Control getControl() {
return tableViewer.getControl();
}
/* @see org.eclipse.ui.part.IPage#setFocus() */
public void setFocus() {
tableViewer.getTable().setFocus();
}
/**
* @return the underlying FileRecord
*/
public FileRecord getResource() {
return resource;
}
/**
* Sets the Column's Widths
*
* @param widths, an Integer-Array containing the widths
*/
public void setColumnWidths(Integer[] widths) {
if (tableViewer.getTable().isDisposed())
return;
TableColumn[] columns = tableViewer.getTable().getColumns();
for (int k = 0; k < widths.length; k++) {
if (widths[k] == null) {
widths[k] = k == 0 ? Integer.valueOf(20) : k == 1 ? Integer.valueOf(170) : Integer.valueOf(40);
}
columns[k].setWidth(widths[k].intValue());
}
System.arraycopy(widths, 0, this.columnWidths, 0, Math.min(this.columnWidths.length, widths.length));
}
/**
* @return an Array with the column widths
*/
public Integer[] getColumnWidths() {
return columnWidths;
}
/**
* Sets the Properties to sort by
*
* @param properties, an Integer-Array with the Number of Column to sort by [0] and the Direction to sort by (-1 or 1) [1]
*/
public void setSorterProperties(Integer[] properties) {
if (properties.length > 0) {
this.currentSortedColumn = properties[0].intValue();
this.columnSortOrder[currentSortedColumn] = properties[1].intValue();
this.tableViewer.setSorter(getViewerSorter(this.currentSortedColumn));
}
}
/**
* @return the properties to sort by
*/
public Integer[] getSorterProperties() {
return new Integer[] { Integer.valueOf(currentSortedColumn), Integer.valueOf(columnSortOrder[currentSortedColumn]) };
}
/**
* Refreshes the View
*/
public void refresh() {
if (!tableViewer.getControl().isDisposed()) {
tableViewer.getControl().setRedraw(false);
tableViewer.refresh();
tableViewer.getControl().setRedraw(true);
}
}
/* @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection selection = (IStructuredSelection) event.getSelection();
IMarker marker = (IMarker) selection.getFirstElement();
if (marker != null) {
IEditorPart editor = getSite().getPage().getActiveEditor();
if (editor != null) {
IEditorInput input = editor.getEditorInput();
if (input instanceof IFileEditorInput) {
IFile file = ((IFileEditorInput) input).getFile();
if (marker.getResource().equals(file)) {
IDE.gotoMarker(editor, marker);
}
}
}
}
}
/**
* Helper method to return an NLS string from its key
*/
private String getString(String key) {
return PMDPlugin.getDefault().getStringTable().getString(key);
}
}