blob: 319918fe4898622758d8908965f90212040924d1 [file] [log] [blame]
/*******************************************************************************
* Copyright 2005, 2012 CHISEL Group, University of Victoria, Victoria, BC,
* Canada. 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: The Chisel Group, University of Victoria IBM CAS, IBM Toronto
* Lab
******************************************************************************/
package org.eclipse.pde.internal.visualization.dependency.views;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.pde.internal.visualization.dependency.PDEVizImages;
import org.eclipse.pde.internal.visualization.dependency.analysis.ErrorReporting;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
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.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
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.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.IMessage;
import org.eclipse.ui.forms.ManagedForm;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormText;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.forms.widgets.TableWrapData;
import org.eclipse.ui.forms.widgets.TableWrapLayout;
import org.eclipse.zest.core.viewers.GraphViewer;
import org.eclipse.zest.core.widgets.Graph;
/**
* This class encapsulates the process of creating the form view in the PDE
* visualization tool.
*/
/* package */class VisualizationForm {
private static final String SymbolicName_Match_Pattern = "Bundle Name Match Regexp";
private static final String SymbolicName_Exclude_Pattern = "Bundle Name Exclude Regexp";
private static final String Hide_Fragments = "Hide Fragments";
/*
* These are all the strings used in the form. These can probably be
* abstracted for internationalization
*/
private static String Plugin_Dependency_Analysis = "Plug-in Dependency Analysis";
private static String Controls = "Options";
private static String Show_Dependency_Path = "Show Dependency Path";
private static String Version_Number = "Show Bundle Version Numbers";
/*
* These are strings and used to determine which radio button is selected
*/
public static String Show_All_Paths = "Show All Paths";
public static String Show_Smart_Path = "Show Smart Path";
public static String Show_Shortest_Path = "Show Shortest Path";
/*
* Some parts of the form we may need access to
*/
private ScrolledForm form;
private FormToolkit toolkit;
private ManagedForm managedForm;
private GraphViewer viewer;
private PluginVisualizationView view;
/*
* Some buttons that we need to access in local methods
*/
private Button showSmartPath = null;
private Button showShortestPath = null;
private Button showAllPaths = null;
private Button dependencyAnalysis = null;
private Button showVersionNumber = null;
private String currentPathAnalysis = null;
private SashForm sash;
private Text searchBox;
private ToolItem cancelIcon;
private Label searchLabel;
/**
* Creates the form.
*
* @param toolKit
* @return
*/
VisualizationForm(Composite parent, FormToolkit toolkit, PluginVisualizationView view) {
this.toolkit = toolkit;
this.view = view;
form = this.toolkit.createScrolledForm(parent);
managedForm = new ManagedForm(this.toolkit, this.form);
createHeaderRegion(form);
FillLayout layout = new FillLayout();
layout.marginHeight = 10;
layout.marginWidth = 4;
form.getBody().setLayout(layout);
this.toolkit.decorateFormHeading(this.form.getForm());
createSash(form.getBody());
}
public void setFocusedNodeName(String nodeName) {
form.setText(Plugin_Dependency_Analysis + ": " + nodeName);
searchBox.setText("");
form.reflow(true);
}
/**
* Creates the header region of the form, with the search dialog, background
* and title. It also sets up the error reporting
* @param form
*/
private void createHeaderRegion(ScrolledForm form) {
Composite headClient = new Composite(form.getForm().getHead(), SWT.NULL);
GridLayout glayout = new GridLayout();
glayout.marginWidth = glayout.marginHeight = 0;
glayout.numColumns = 3;
headClient.setLayout(glayout);
headClient.setBackgroundMode(SWT.INHERIT_DEFAULT);
searchLabel = new Label(headClient, SWT.NONE);
searchLabel.setText("Search:");
searchBox = toolkit.createText(headClient, "");
GridData data = new GridData();
data.widthHint = 300;
searchBox.setLayoutData(data);
ToolBar cancelBar = new ToolBar(headClient, SWT.FLAT );
cancelIcon = new ToolItem(cancelBar, SWT.NONE);
cancelIcon.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
searchBox.setText("");
}
});
cancelIcon.setImage(PDEVizImages.get(PDEVizImages.IMG_SEARCH_CANCEL));
toolkit.paintBordersFor(headClient);
form.setHeadClient(headClient);
searchBox.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
if (searchBox.getText().length() > 0) {
cancelIcon.setEnabled(true);
} else {
cancelIcon.setEnabled(false);
}
}
});
cancelIcon.setEnabled(false);
form.setText(Plugin_Dependency_Analysis);
form.setImage(PDEVizImages.get(PDEVizImages.IMG_REQ_PLUGIN_OBJ));
enableSearchBox(false);
// Add a hyperlink listener for the messages
form.getForm().addMessageHyperlinkListener(new HyperlinkAdapter() {
public void linkActivated(org.eclipse.ui.forms.events.HyperlinkEvent e) {
String title = e.getLabel();
Object href = e.getHref();
if (href instanceof IMessage[] && ((IMessage[]) href).length > 1) {
Point hl = ((Control) e.widget).toDisplay(0, 0);
hl.x += 10;
hl.y += 10;
final Shell shell = new Shell(VisualizationForm.this.form.getShell(), SWT.ON_TOP | SWT.TOOL);
shell.setImage(getImage(VisualizationForm.this.form.getMessageType()));
shell.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
GridLayout layout = new GridLayout();
layout.numColumns = 1;
layout.verticalSpacing = 0;
shell.setText(title);
shell.setLayout(layout);
Link link = new Link(shell, SWT.NONE);
link.setText("<A>close</A>");
GridData data = new GridData(SWT.RIGHT, SWT.CENTER, false, false);
link.setLayoutData(data);
link.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
shell.close();
}
});
Group group = new Group(shell, SWT.NONE);
data = new GridData(SWT.LEFT, SWT.TOP, true, true);
group.setLayoutData(data);
group.setLayout(layout);
group.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
FormText text = toolkit.createFormText(group, true);
configureFormText(VisualizationForm.this.form.getForm(), text);
if (href instanceof IMessage[]) {
text.setText(createFormTextContent((IMessage[]) href), true, false);
}
shell.setLocation(hl);
shell.pack();
shell.open();
} else if (href instanceof IMessage[]) {
IMessage oneMessage = ((IMessage[]) href)[0];
ErrorReporting error = (ErrorReporting) oneMessage.getData();
if (error != null) {
error.handleError();
}
}
}
});
}
private void configureFormText(final Form form, FormText text) {
text.addHyperlinkListener(new HyperlinkAdapter() {
public void linkActivated(HyperlinkEvent e) {
String is = (String) e.getHref();
try {
((FormText) e.widget).getShell().dispose();
int index = Integer.parseInt(is);
IMessage[] messages = form.getChildrenMessages();
IMessage message = messages[index];
ErrorReporting error = (ErrorReporting) message.getData();
if (error != null) {
error.handleError();
}
} catch (NumberFormatException ex) {
}
}
});
text.setImage("error", getImage(IMessageProvider.ERROR));
text.setImage("warning", getImage(IMessageProvider.WARNING));
text.setImage("info", getImage(IMessageProvider.INFORMATION));
}
String createFormTextContent(IMessage[] messages) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.println("<form>");
for (int i = 0; i < messages.length; i++) {
IMessage message = messages[i];
pw.print("<li vspace=\"false\" style=\"image\" indent=\"16\" value=\"");
switch (message.getMessageType()) {
case IMessageProvider.ERROR:
pw.print("error");
break;
case IMessageProvider.WARNING:
pw.print("warning");
break;
case IMessageProvider.INFORMATION:
pw.print("info");
break;
}
pw.print("\"> <a href=\"");
pw.print(i + "");
pw.print("\">");
if (message.getPrefix() != null) {
pw.print(message.getPrefix());
}
pw.print(message.getMessage());
pw.println("</a></li>");
}
pw.println("</form>");
pw.flush();
return sw.toString();
}
/**
* Creates the sashform to separate the graph from the controls.
*
* @param parent
*/
private void createSash(Composite parent) {
sash = new SashForm(parent, SWT.NONE);
this.toolkit.paintBordersFor(parent);
createGraphSection(sash);
createControlsSection(sash);
sash.setWeights(new int[] { 10, 3 });
}
private class MyGraphViewer extends GraphViewer {
public MyGraphViewer(Composite parent, int style) {
super(parent, style);
Graph graph = new Graph(parent, style) {
public Point computeSize(int hint, int hint2, boolean changed) {
return new Point(0, 0);
}
};
setControl(graph);
}
}
/**
* Creates the section of the form where the graph is drawn
*
* @param parent
*/
private void createGraphSection(Composite parent) {
Section section = this.toolkit.createSection(parent, Section.TITLE_BAR);
viewer = new MyGraphViewer(section, SWT.NONE);
section.setClient(viewer.getControl());
}
private void setDependencyPath(boolean enabled) {
if (showAllPaths.getEnabled() != enabled) {
showAllPaths.setEnabled(enabled);
}
if (showSmartPath.getEnabled() != enabled) {
showSmartPath.setEnabled(enabled);
}
if (showShortestPath.getEnabled() != enabled) {
showShortestPath.setEnabled(enabled);
}
if (!enabled) {
showAllPaths.setSelection(false);
showSmartPath.setSelection(false);
showShortestPath.setSelection(false);
} else {
if (currentPathAnalysis == Show_All_Paths) {
showAllPaths.setSelection(true);
} else if (currentPathAnalysis == Show_Smart_Path) {
showSmartPath.setSelection(true);
} else if (currentPathAnalysis == Show_Shortest_Path) {
showShortestPath.setSelection(true);
}
}
view.setDependencyPath(enabled, currentPathAnalysis);
}
/**
* Creates the section holding the analysis controls.
*
* @param parent
*/
private void createControlsSection(Composite parent) {
Section controls = this.toolkit.createSection(parent, Section.TITLE_BAR | Section.EXPANDED);
controls.setText(Controls);
Composite controlComposite = new Composite(controls, SWT.NONE) {
public Point computeSize(int hint, int hint2, boolean changed) {
return new Point(0, 0);
}
};
this.toolkit.adapt(controlComposite);
controlComposite.setLayout(new GridLayout());
showVersionNumber = this.toolkit.createButton(controlComposite, Version_Number, SWT.CHECK);
showVersionNumber.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
showVersionNumber.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
view.showVersionNumber(showVersionNumber.getSelection());
}
});
dependencyAnalysis = this.toolkit.createButton(controlComposite, Show_Dependency_Path, SWT.CHECK);
dependencyAnalysis.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
dependencyAnalysis.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
setDependencyPath(((Button) e.getSource()).getSelection());
}
});
Section dependencyOptions = this.toolkit.createSection(controlComposite, Section.EXPANDED | Section.NO_TITLE);
dependencyOptions.setLayout(new FillLayout());
Composite dependencyOptionsComposite = this.toolkit.createComposite(dependencyOptions);
dependencyOptionsComposite.setLayout(new TableWrapLayout());
showSmartPath = this.toolkit.createButton(dependencyOptionsComposite, Show_Smart_Path, SWT.RADIO);
showSmartPath.setLayoutData(new TableWrapData(TableWrapData.FILL));
showSmartPath.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
currentPathAnalysis = Show_Smart_Path;
view.setDependencyPath(dependencyAnalysis.getSelection(), currentPathAnalysis);
}
});
showAllPaths = this.toolkit.createButton(dependencyOptionsComposite, Show_All_Paths, SWT.RADIO);
showAllPaths.setLayoutData(new TableWrapData(TableWrapData.FILL));
showAllPaths.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
currentPathAnalysis = Show_All_Paths;
view.setDependencyPath(dependencyAnalysis.getSelection(), currentPathAnalysis);
}
});
showShortestPath = this.toolkit.createButton(dependencyOptionsComposite, Show_Shortest_Path, SWT.RADIO);
showShortestPath.setLayoutData(new TableWrapData(TableWrapData.FILL));
showShortestPath.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
currentPathAnalysis = Show_Shortest_Path;
view.setDependencyPath(dependencyAnalysis.getSelection(), currentPathAnalysis);
}
});
currentPathAnalysis = Show_Smart_Path;
setDependencyPath(false);
dependencyOptions.setClient(dependencyOptionsComposite);
Composite filteringComposite = this.toolkit.createComposite(controlComposite, SWT.NONE);
filteringComposite.setLayout(new GridLayout(1, false));
final Button hideFragmentsButton = this.toolkit.createButton(filteringComposite, Hide_Fragments, SWT.CHECK);
hideFragmentsButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
view.setHideFragments(hideFragmentsButton.getSelection());
}
});
this.toolkit.createLabel(filteringComposite, SymbolicName_Match_Pattern);
final Text symbolicNamesMatchPattern = this.toolkit.createText(filteringComposite, "", SWT.BORDER);
symbolicNamesMatchPattern.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
symbolicNamesMatchPattern.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent arg0) {
view.setSymbolicNameMatchPattern(symbolicNamesMatchPattern.getText());
}
});
this.toolkit.createLabel(filteringComposite, SymbolicName_Exclude_Pattern);
final Text symbolicNamesExcludePattern = this.toolkit.createText(filteringComposite, "", SWT.BORDER);
symbolicNamesExcludePattern.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
symbolicNamesExcludePattern.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent arg0) {
view.setSymbolicNameExcludePattern(symbolicNamesExcludePattern.getText());
}
});
controls.setClient(controlComposite);
}
Button getDependencyAnalysis() {
return dependencyAnalysis;
}
/**
* Gets the currentGraphViewern
*
* @return
*/
public GraphViewer getGraphViewer() {
return viewer;
}
/**
* Gets the form we created.
*/
public ScrolledForm getForm() {
return form;
}
public ManagedForm getManagedForm() {
return managedForm;
}
public Text getSearchBox() {
return this.searchBox;
}
public void enableSearchBox(boolean enable) {
this.searchLabel.setEnabled(enable);
this.searchBox.setEnabled(enable);
}
private Image getImage(int type) {
switch (type) {
case IMessageProvider.ERROR:
return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_ERROR_TSK);
case IMessageProvider.WARNING:
return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_WARN_TSK);
case IMessageProvider.INFORMATION:
return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_INFO_TSK);
}
return null;
}
}