blob: e0572069bf4519cdee1797ea0066920709bac818 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 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:
* Abhishek Sharma, UIUC - Initial API and implementation
*******************************************************************************/
package org.eclipse.rephraserengine.internal.ui.browser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.rephraserengine.core.vpg.IVPGNode;
import org.eclipse.rephraserengine.core.vpg.VPGEdge;
import org.eclipse.rephraserengine.core.vpg.eclipse.EclipseVPG;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CaretEvent;
import org.eclipse.swt.custom.CaretListener;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
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.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
/**
* The Edges tab in the VPG Browser.
*
* @author Abhishek Sharma
*/
class EdgesTab
{
private TabItem edges;
private Composite composite;
private StyledText styledText;
private Button showAll;
private Button showSelected;
private Button edgeButton ;
private String filename;
private List<VPGEdge<?,?,?>> edgesInFile;
private Set<VPGEdge<?,?,?>> showEdges;
private EclipseVPG vpg;
private Set<Integer> edgeTypes;
private Set<Integer> edgeTypesToShow;
private List<Color> color ;
private Label label;
public EdgesTab(TabItem edges, TabFolder tabFolder, EclipseVPG vpg)
{
this.vpg = vpg ;
this.filename = null;
this.edgesInFile = Collections.emptyList();
this.showEdges = Collections.emptySet();
this.edges = edges;
this.edgeTypes = Collections.emptySet();
this.edgeTypesToShow = new HashSet<Integer>();
this.color = Collections.emptyList();
color = new ArrayList<Color>();
addColors();
createControls(tabFolder);
}
/** Adds three new colors red,green and blue to the color list
*
*/
private void addColors()
{
//Adds three new colors red,green and blue to the color list
color.add(new Color(null, new RGB(192,0,0)));
color.add(new Color(null, new RGB(0,192,0)));
color.add(new Color(null, new RGB(0,0,192)));
}
private void createControls(TabFolder tabfolder)
{
createComposite(tabfolder);
createRadioButtons();
createEdgesMenu();
createStyledText();
createLabel();
}
private void createLabel()
{
label= new Label(composite, SWT.NONE);
label.setText(""); //$NON-NLS-1$
}
private void createEdgesMenu()
{
edgeButton = new Button(composite, SWT.FLAT);
edgeButton.setText(Messages.EdgesTab_EdgeTypes);
edgeButton.addSelectionListener(new ShowEdgeTypesMenu());
}
private class ShowEdgeTypesMenu implements SelectionListener
{
public void widgetSelected(SelectionEvent e)
{
Menu popupMenu = new Menu(edgeButton);
//This loop creates the Menu items and adds them to the menu.The Menu items
//are the types of edges present in the file
for (Integer type : edgeTypes)
{
MenuItem menuItem = new MenuItem(popupMenu, SWT.CHECK);
menuItem.setText(vpg.describeEdgeType(type));
menuItem.addSelectionListener(new MenuItemSelectionListener(type));
menuItem.setSelection(edgeTypesToShow.contains(type));
}
new MenuItem(popupMenu, SWT.SEPARATOR);
MenuItem menuItem = new MenuItem(popupMenu, SWT.CHECK);
menuItem.setText(Messages.EdgesTab_ShowAllEdges);
menuItem.addSelectionListener(new SelectAllSelectionListener());
popupMenu.setVisible(true);
while (!popupMenu.isDisposed() && popupMenu.isVisible())
if (!popupMenu.getDisplay().readAndDispatch())
popupMenu.getDisplay().sleep();
popupMenu.dispose();
}
public void widgetDefaultSelected(SelectionEvent e)
{
widgetSelected(e);
}
}
private class MenuItemSelectionListener implements SelectionListener
{
private int edgeType;
public MenuItemSelectionListener(int type)
{
this.edgeType = type;
}
public void widgetSelected(SelectionEvent e)
{
//If the menu item has already been selected and clicked on once again
//de-select it
if (edgeTypesToShow.contains(edgeType)){
edgeTypesToShow.remove(edgeType);
}
else
edgeTypesToShow.add(edgeType);
styledText.redraw();
}
public void widgetDefaultSelected(SelectionEvent e)
{
widgetSelected(e);
}
}
private class SelectAllSelectionListener implements SelectionListener{
public SelectAllSelectionListener(){
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetSelected(SelectionEvent e)
{
edgeTypesToShow.addAll(edgeTypes);
showEdges = collectSelectedEdges(styledText.getCaretOffset());
styledText.redraw();
}
/* (non-Javadoc)
* @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
*/
public void widgetDefaultSelected(SelectionEvent e)
{
widgetSelected(e);
}
}
private Set<VPGEdge<?,?,?>> collectSelectedEdges(int caretOffset)
{
//if the care offset happens to be within the edge then add the edge to the edgesToShow list
HashSet<VPGEdge<?,?,?>> edgesToShow = new HashSet<VPGEdge<?,?,?>>();
for (VPGEdge<?,?,?> edge : edgesInFile)
{
if (edge.getSource().getOffset() <= caretOffset
&& edge.getSource().getEndOffset() >= caretOffset)
{
edgesToShow.add(edge);
}
else if (edge.getSink().getOffset() <= caretOffset
&& edge.getSink().getEndOffset() >= caretOffset)
{
edgesToShow.add(edge);
}
}
return edgesToShow;
}
private void createComposite(TabFolder tabfolder)
{
GridLayout layout = new GridLayout();
layout.numColumns = 3;
composite = new Composite(tabfolder, SWT.NONE);
composite.setLayout(layout);
edges.setControl(composite);
}
private void createRadioButtons()
{
createShowAllButton();
createShowSelectedButton();
}
private void createShowAllButton()
{
showAll = new Button(composite, SWT.RADIO);
showAll.setText(Messages.EdgesTab_ShowAllEdges);
showAll.setSelection(false);
showAll.addSelectionListener(new RadioButtonSelectionListener());
}
private void createShowSelectedButton()
{
showSelected = new Button(composite, SWT.RADIO);
showSelected.setText(Messages.EdgesTab_ShowSelectedEdges);
showSelected.setSelection(true);
showSelected.addSelectionListener(new RadioButtonSelectionListener());
}
private final class RadioButtonSelectionListener implements SelectionListener
{
public void widgetSelected(SelectionEvent e)
{
styledText.redraw();
}
public void widgetDefaultSelected(SelectionEvent e)
{
widgetSelected(e);
}
}
private void createStyledText()
{
styledText = new StyledText(composite, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.READ_ONLY);
GridData gridData = new GridData();
gridData.horizontalAlignment = GridData.FILL;
gridData.verticalAlignment = GridData.FILL;
gridData.grabExcessVerticalSpace = true;
gridData.grabExcessHorizontalSpace = true;
gridData.horizontalSpan = 3;
gridData.verticalSpan = 1;
styledText.setLayoutData(gridData);
styledText.setFont(JFaceResources.getTextFont());
styledText.addPaintListener(new EdgePainter(styledText));
styledText.addCaretListener(new ShowEdgeCaretListener());
}
private final class ShowEdgeCaretListener implements CaretListener
{
public void caretMoved(CaretEvent event)
{
showEdges = collectSelectedEdges(event.caretOffset);
displayCaretInformation(event);
styledText.redraw();
}
private void displayCaretInformation(CaretEvent event)
{
int caretLine = styledText.getLineAtOffset(styledText.getCaretOffset());
int lineOffset = styledText.getOffsetAtLine(caretLine);
int caretOffset = styledText.getCaretOffset();
int caretColumn = caretOffset-lineOffset+1 ;
label.setText(
Messages.bind(
Messages.EdgesTab_LineColOffset, new Object[] {
caretLine+1,
caretColumn,
styledText.getCaretOffset() }));
label.pack();
}
}
private final class EdgePainter implements PaintListener
{
private final StyledText styledText;
private EdgePainter(StyledText styledText)
{
this.styledText = styledText;
}
public void paintControl(PaintEvent e)
{
//Depending upon whether if edgesTypesToShow list contains an edge this loop draws a rectangle around
//the edge and calls the constructor of the DrawEdgesAndArrows class to draw lines between the source and sink
for (VPGEdge< ? , ? , ? > edge : edgesInFile)
{
if (edgeTypesToShow.contains(edge.getType()))
{
Color defaultColor = e.gc.getForeground();
//depending upon the type of edge the color of the edges and lines is decided.
e.gc.setForeground(setColor(edge.getType()));
IVPGNode source = edge.getSource();
IVPGNode sink = edge.getSink();
if (source.getFilename().equals(filename) && sink.getFilename().equals(filename))
{
Rectangle srcRect = drawRectangle(e, source.getOffset(), source.getEndOffset());
Rectangle sinkRect = drawRectangle(e, sink.getOffset(), sink.getEndOffset());
if (srcRect != null && sinkRect != null)
{
if(showAll.getSelection()||showEdges.contains(edge)){
displayEdgesAndArrows(e.gc,sinkRect,srcRect);
}
}
}
else
{
// TODO: Handle this case later
}
e.gc.setForeground(defaultColor);
}
}
}
private void displayEdgesAndArrows(GC gc, Rectangle sinkRect, Rectangle srcRect)
{
new EdgeArrow(srcRect, sinkRect).drawOn(gc);
}
private Color setColor(int type)
{
return color.get(type%color.size());
}
private Rectangle drawRectangle(PaintEvent e, int startOffset, int endOffset)
{
if (isValid(startOffset) && isValid(endOffset))
{
Rectangle srcRect = styledText.getTextBounds(startOffset, Math.max(0, endOffset-1));
e.gc.drawRectangle(srcRect);
return srcRect;
}
else
return null;
}
private boolean isValid(int offset)
{
return offset >= 0 && offset < styledText.getCharCount();
}
}
@SuppressWarnings("unchecked")
public void showEdges(String file_selected, EclipseVPG vpg)
{
this.filename = file_selected;
Object ast = vpg.acquireTransientAST(filename);
if (ast == null)
styledText.setText(Messages.bind(Messages.EdgesTab_UnableToParse, filename));
else
styledText.setText(vpg.getSourceCodeFromAST(ast));
edgesInFile = new ArrayList<VPGEdge< ? , ? , ? >>();
for (VPGEdge< ? , ? , ? > edge : (Iterable<VPGEdge< ? , ? , ? >>)vpg.getAllEdgesFor(filename))
edgesInFile.add(edge);
edgeTypes = new HashSet<Integer>();
for (VPGEdge<?,?,?> edge : (Iterable<VPGEdge<?,?,? >>)vpg.getAllEdgesFor(filename))
edgeTypes.add(edge.getType());
edgeButton.setEnabled(edgeTypes.size() != 0);
}
}