blob: 6dd51380b4e37a0ab48f599d4b2720a260616a7d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 University of Illinois at Urbana-Champaign 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:
* UIUC - Initial API and implementation
*******************************************************************************/
package org.eclipse.photran.internal.ui.views.vpgproblems;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.MultiRule;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.photran.internal.core.vpg.PhotranVPG;
import org.eclipse.rephraserengine.core.vpg.VPGLog;
import org.eclipse.rephraserengine.core.vpg.eclipse.VPGSchedulingRule;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
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.part.ViewPart;
import org.eclipse.ui.texteditor.MarkerUtilities;
/**
* Fortran Analysis/Refactoring Problems view, A.K.A. VPG Problems view.
* <p>
* Based on Eclipse JFace TableView Tutorial; thanks to Lars Vogel
* for posting the tutorial
* (http://www.vogella.de/articles/EclipseJFaceTable/aritcle.html)
* Based on samples provided in Java DeveloperÕs Guide to Eclipse,
* Chapter 18 (http://www.jdg2e.com/ch18.views/doc/index.htm and
* http://www.jdg2e.com/jdg2e_CD_for_eclipse321/plug-in_development/examples/com.ibm.jdg2e.view.marker/src-marker/com/ibm/jdg2e/view/marker/MarkerView.java)
* © Copyright International Business Machines Corporation, 2003, 2004, 2006.
* All Rights Reserved.
* Code or samples provided therein are provided without warranty of any kind.
*
* @author Timofey Yuvashev
*
* @author Esfar Huq
* @author Rui Wang
*
* Replaced call to setSorter() to setComparator() in method createPartControl()
*/
public class VPGProblemView extends ViewPart implements VPGLog.ILogListener
{
static enum VPGViewColumn
{
DESCRIPTION("Description", 44),
RESOURCE("Resource", 10),
PATH("Path", 20);
public final String name;
public final int width;
private VPGViewColumn(String name, int width)
{
this.name = name;
this.width = width;
}
}
private static RecreateMarkers markersTask = null;
private TableViewer tableViewer = null;
private TableSorter tableSorter = null;
private Clipboard clipboard = null;
private CopyMarkedFileAction copyAction = null;
private OpenMarkedFileAction openAction = null;
private ShowFullMessageAction showAction = null;
//private RemoveMarkerAction remAction = null;
//private VPGViewFilterAction infosMarkerFilterAction = null;
private VPGViewFilterAction warningsMarkerFilterAction = null;
private VPGViewFilterAction errorsMarkerFilterAction = null;
//TODO: Depending on how we will handle updates to markers, we might need a
// way to update this array. Currently, it is populated as Workbench's start-time
// and remains unchaged since then
public static int[] MARKER_COUNT = {0,0,0}; //Number of Infos, Warnings and Errors respectively
@Override
public void createPartControl(Composite parent)
{
GridLayout overallLayout = new GridLayout(1,false);
parent.setLayout(overallLayout);
createTableViewer(parent);
createTableColumns(tableViewer);
setTableGridData();
getSite().setSelectionProvider(tableViewer);
//TODO: Change the default string
MenuManager manager = createMenuManager();
getSite().registerContextMenu(manager, tableViewer);
tableViewer.setContentProvider(new VPGProblemContentProvider());
tableViewer.setLabelProvider(new VPGProblemLabelProvider());
PhotranVPG.getInstance().log.addLogListener(this);
createToolbarButtons();
initEvents();
}
private void createTableViewer(Composite parent)
{
tableViewer = new TableViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL
| SWT.MULTI | SWT.FULL_SELECTION);
tableSorter = new TableSorter();
tableViewer.setComparator(this.tableSorter);
}
private MenuManager createMenuManager()
{
MenuManager manager = new VPGProblemContextMenu(getViewSite(), "Problems View Menu");
tableViewer.getTable().setMenu(manager.createContextMenu(tableViewer.getTable()));
return manager;
}
public void onLogChange()
{
if (markersTask == null)
{
// If non-null, this task is already running; don't start a 2nd instance
markersTask = new RecreateMarkers();
WorkspaceJob job = new RecreateMarkers();
job.setRule(MultiRule.combine(VPGSchedulingRule.getInstance(),
ResourcesPlugin.getWorkspace().getRoot()));
job.schedule();
}
}
private class RecreateMarkers extends WorkspaceJob
{
private RecreateMarkers()
{
super("Updating Fortran Analysis/Refactoring Problems view");
}
@Override public IStatus runInWorkspace(final IProgressMonitor monitor)
{
final List<IMarker> markers = PhotranVPG.getInstance().recomputeErrorLogMarkers();
getSite().getShell().getDisplay().syncExec(new Runnable()
{
public void run()
{
Table t = tableViewer.getTable();
t.removeAll();
t.update();
tableViewer.setInput(markers);
countMarkers(markers);
if (warningsMarkerFilterAction != null && errorsMarkerFilterAction != null)
{
String warnStr = String.valueOf(MARKER_COUNT[IMarker.SEVERITY_WARNING]) + " Warnings";
String errStr = String.valueOf(MARKER_COUNT[IMarker.SEVERITY_ERROR]) + " Errors";
warningsMarkerFilterAction.setText(warnStr);
errorsMarkerFilterAction.setText(errStr);
}
}
});
markersTask = null;
return Status.OK_STATUS;
}
}
private void setTableGridData()
{
GridData tableData = new GridData();
tableData.grabExcessHorizontalSpace = true;
tableData.grabExcessVerticalSpace = true;
tableData.horizontalAlignment = GridData.FILL;
tableData.verticalAlignment = GridData.FILL;
tableViewer.getTable().setLayoutData(tableData);
}
private void resetMarkerCount()
{
for(int i = 0; i < MARKER_COUNT.length; ++i)
{
MARKER_COUNT[i] = 0;
}
}
private void countMarkers(List<IMarker> markers)
{
//Get all the markers in the workspace
//IMarker[] markers = ResourcesPlugin.getWorkspace().getRoot().findMarkers(null, true, IResource.DEPTH_INFINITE);
resetMarkerCount();;
//HACK
for(IMarker marker : markers)
{
int sev = MarkerUtilities.getSeverity(marker);
if(sev == IMarker.SEVERITY_ERROR ||
sev == IMarker.SEVERITY_WARNING ||
sev == IMarker.SEVERITY_INFO)
MARKER_COUNT[sev]++;
}
}
private void createActions()
{
copyAction = new CopyMarkedFileAction(this, "Copy");
openAction = new OpenMarkedFileAction(getSite());
showAction = new ShowFullMessageAction(getSite());
//remAction = new RemoveMarkerAction(getSite());
//int sevInfo = IMarker.SEVERITY_INFO;
int sevWarn = IMarker.SEVERITY_WARNING;
int sevErr = IMarker.SEVERITY_ERROR;
// Copy list to avoid ConcurrentModificationException
List<IMarker> markers = new ArrayList<IMarker>(PhotranVPG.getInstance().recomputeErrorLogMarkers());
countMarkers(markers);
//String infoStr = String.valueOf(MARKER_COUNT[sevInfo]) + " Infos";
String warnStr = String.valueOf(MARKER_COUNT[sevWarn]) + " Warnings";
String errStr = String.valueOf(MARKER_COUNT[sevErr]) + " Errors";
/*infosMarkerFilterAction = new VPGViewFilterAction(tableViewer,
infoStr,
sevInfo);*/
warningsMarkerFilterAction = new VPGViewFilterAction(tableViewer,
warnStr,
sevWarn);
errorsMarkerFilterAction = new VPGViewFilterAction(tableViewer,
errStr,
sevErr);
}
private void addActionsToToolbar()
{
IToolBarManager toolBarManager = getViewSite().getActionBars().getToolBarManager();
toolBarManager.add(errorsMarkerFilterAction);
toolBarManager.add(warningsMarkerFilterAction);
//toolBarManager.add(infosMarkerFilterAction);
toolBarManager.add(openAction);
toolBarManager.add(copyAction);
//toolBarManager.add(remAction);
toolBarManager.add(new Separator());
toolBarManager.add(showAction);
}
private void addTableViewerSelectionChangeListener()
{
tableViewer.addSelectionChangedListener(new ISelectionChangedListener()
{
public void selectionChanged(SelectionChangedEvent e)
{
boolean isEnabled = !e.getSelection().isEmpty();
openAction.setEnabled(isEnabled);
copyAction.setEnabled(isEnabled);
//remAction.setEnabled(isEnabled);
showAction.setEnabled(isEnabled);
}
});
}
private void createToolbarButtons()
{
createActions();
openAction.setEnabled(false);
copyAction.setEnabled(false);
//remAction.setEnabled(false);
showAction.setEnabled(false);
addActionsToToolbar();
addTableViewerSelectionChangeListener();
}
/*
* Creates layout for a table. Simply adds ColumnData to each column in the table,
* setting that column's width to pre-defined value
*/
private TableLayout createTableLayout()
{
TableLayout layout = new TableLayout();
for (VPGViewColumn col : VPGViewColumn.values())
layout.addColumnData(new ColumnWeightData(col.width, true));
return layout;
}
/*
* Creates columns for the table contained in TableViewer.
* Assigns them name, size, alignment and adds a selectionListener
* that is responsible for sorting that column, if it is clicked on
*/
private void createTableColumns(final TableViewer viewer)
{
Table table = viewer.getTable();
TableLayout layout = createTableLayout();
table.setLayout(layout);
for (final VPGViewColumn vpgCol : VPGViewColumn.values())
{
final TableColumn viewerCol = new TableViewerColumn(viewer, SWT.NONE).getColumn();
viewerCol.setText(vpgCol.name);
viewerCol.setToolTipText(vpgCol.name);
viewerCol.setAlignment(SWT.LEFT);
viewerCol.setResizable(true);
viewerCol.setMoveable(true);
viewerCol.addSelectionListener(new ColumnSelectionListener(viewerCol, vpgCol, viewer));
}
table.setLinesVisible(true);
table.setHeaderVisible(true);
}
private final class ColumnSelectionListener extends SelectionAdapter
{
private final TableColumn column;
private final VPGViewColumn col;
private final TableViewer viewer;
private ColumnSelectionListener(TableColumn column, VPGViewColumn col, TableViewer viewer)
{
this.column = column;
this.col = col;
this.viewer = viewer;
}
public void widgetSelected(SelectionEvent e)
{
tableSorter.setColumn(col.ordinal());
int dir = viewer.getTable().getSortDirection();
if(viewer.getTable().getSortColumn() == column)
dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
else
dir = SWT.DOWN;
viewer.getTable().setSortDirection(dir);
viewer.getTable().setSortColumn(column);
viewer.refresh();
}
}
/*
* Initializes event Listeners and Actions for the Table
*/
private void initEvents()
{
tableViewer.getTable().addMouseListener(new DoubleClickListener());
}
private final class DoubleClickListener extends MouseAdapter
{
public void mouseDoubleClick(MouseEvent dblClick)
{
Table t = (Table)dblClick.getSource();
for (TableItem item : t.getSelection())
if (item.getData() instanceof IMarker)
openMarker((IMarker)item.getData());
}
private void openMarker(IMarker marker)
{
if (marker.getResource() != null)
new OpenMarkedFileAction(getViewSite()).run(marker);
}
}
public Clipboard getClipboard()
{
if(clipboard == null)
clipboard = new Clipboard(getSite().getShell().getDisplay());
return clipboard;
}
@Override
public void setFocus()
{
tableViewer.getControl().setFocus();
}
//TODO: Should we remove more stuff?
@Override
public void dispose()
{
if (clipboard != null)
clipboard.dispose();
super.dispose();
}
}