Java tutorial
/** * Copyright (c) 2006-2010 MoVe - Laboratoire d'Informatique de Paris 6 (LIP6). * 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: * Jean-Baptiste VORON (LIP6) - Project Head / Initial contributor * Clment DMOULINS (LIP6) - Project Manager * * Official contacts: * coloane@lip6.fr * http://coloane.lip6.fr */ package fr.lip6.move.coloane.tools.layout; import fr.lip6.move.coloane.tools.graphviz.GraphVizActivator; import fr.lip6.move.coloane.tools.graphviz.GraphVizActivator.DotAlgo; import fr.lip6.move.coloane.tools.graphviz.GraphVizActivator.DotMethod; import java.io.File; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.swt.SWT; 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.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; /** * The preferences page contributed by the plugin. * @author Yann Thierry-Mieg */ public class GraphVizPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { private Button automaticDotButton; private Button useBundledDotButton; private Button autodetectDotButton; private Button specifyDotButton; @SuppressWarnings("unused") private Button specifyAlgoButton; private FileBrowserField dotBrowser; private Button dotDotButton; private Button neatoDotButton; private Button fdpDotButton; private Button circoDotButton; /** * Creates the mildly complex radio buttons that the prefs dialog uses. * * @param group The group to add the button to. * @param label The text for the button's label * @param enabled enabled/disabled. * @param method If this matches the current method, the button is automatically selected. * @return The new button. */ private Button createButton(Group group, String label, boolean enabled, DotMethod method) { Button button; button = createRadioButton(group, label); button.setSelection(getCurrentDotMethod() == method); button.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { boolean enabled = specifyDotButton.getSelection(); dotBrowser.setEnabled(enabled); dotBrowserChanged(null); } }); button.setEnabled(enabled); return button; } /** * Creates the mildly complex radio buttons that the preferences dialog uses.<br> * Here code for the radio selection algorithm button. * * @param group The group to add the button to. * @param label The text for the button's label * @param enabled Not really sure what this is for. * @param method If this matches the current method, the button is automatically selected. * @return The new button. */ private Button createButton(Group group, String label, boolean enabled, DotAlgo method) { Button button; button = createRadioButton(group, label); button.setSelection(getCurrentDotAlgo() == method); button.setEnabled(enabled); return button; } /** * Creates the composite which will contain all the preference controls for this page. * * @param parent the parent composite * @return the composite for this page */ private Composite createComposite(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; composite.setLayout(layout); composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL)); return composite; } /** * {@inheritDoc} * @see org.eclipse.jface.preference.PreferencePage */ @Override protected final Control createContents(Composite parent) { Composite composite = createComposite(parent); createOpenModeGroup(composite); createAlgoModeGroup(composite); applyDialogFont(composite); return composite; } /** * Builds up the algorithm choice zone. * @param composite the parent in which we add stuff. */ private void createAlgoModeGroup(Composite composite) { Group buttonComposite = new Group(composite, SWT.LEFT); GridLayout layout = new GridLayout(); buttonComposite.setLayout(layout); GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL); buttonComposite.setLayoutData(data); buttonComposite.setText("Dot layout algorithm"); dotDotButton = createButton(buttonComposite, "dot (acyclic graph)", true, DotAlgo.DOT); dotDotButton.setToolTipText( "A mode adapted to acyclic graphs, a good setting for decision diagrams for instance. \n" + "Depending on the graph, may work well also for state space graphs, although neato is also a good option."); neatoDotButton = createButton(buttonComposite, "neato (spring model/energy based) [recommended]", true, DotAlgo.NEATO); neatoDotButton.setToolTipText( "A mode base on a spring model, well adapted to graphs with cycles. This setting gives best results for Petri net and their variants."); fdpDotButton = createButton(buttonComposite, "fdp (spring model/force based)", true, DotAlgo.FDP); fdpDotButton.setToolTipText( "A mode base on a spring model, with a different algorithm wrt neato. Supports larger graphs better than neato, and allows clustering."); circoDotButton = createButton(buttonComposite, "circo (circular layout)", true, DotAlgo.CIRCO); circoDotButton.setToolTipText( "A circular layout, nodes are placed on a circle. This setting gives poor results with Petri nets."); } /** * Build the area with dot detection options. * @param composite the parent in which we add stuff. */ private void createOpenModeGroup(Composite composite) { Group buttonComposite = new Group(composite, SWT.LEFT); GridLayout layout = new GridLayout(); buttonComposite.setLayout(layout); GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL); buttonComposite.setLayoutData(data); buttonComposite.setText("Dot executable to use"); GraphVizActivator graphviz = GraphVizActivator.getInstance(); automaticDotButton = createButton(buttonComposite, "Choose Automatically", true, DotMethod.AUTO); useBundledDotButton = createButton(buttonComposite, "Bundled", graphviz.hasBundledInstall(), DotMethod.BUNDLE); String detectedDotLocation = graphviz.autodetectDots(); boolean dotDetected = detectedDotLocation != null; String detectLabel = "Detected: "; if (dotDetected) { detectLabel += detectedDotLocation; } else { detectLabel += "(none)"; } autodetectDotButton = createButton(buttonComposite, detectLabel, dotDetected, DotMethod.DETECT); specifyDotButton = createButton(buttonComposite, "Specify Manually:", true, DotMethod.MANUAL); dotBrowser = new FileBrowserField(buttonComposite) { @Override public void valueChanged() { dotBrowserChanged(getText()); } }; dotBrowser.setText(graphviz.getManualDotPath()); dotBrowser.setEnabled(getCurrentDotMethod() == DotMethod.MANUAL); data = new GridData(); data.horizontalIndent = 20; data.horizontalAlignment = GridData.FILL; data.grabExcessHorizontalSpace = true; dotBrowser.setLayoutData(data); } /** * Called when user has done something. Grab the path text. * @param txt the new text */ public final void dotBrowserChanged(String txt) { setErrorMessage(null); setMessage(null); String newText = txt; if (newText == null) { newText = dotBrowser.getText(); } if (specifyDotButton.getSelection()) { if (newText.length() == 0) { setErrorMessage("Please enter a path."); setValid(false); return; } File dotFile = new File(newText); String fileName = dotFile.getName(); int extensionPos; while ((extensionPos = fileName.lastIndexOf('.')) > 0) { fileName = fileName.substring(0, extensionPos); } if (!dotFile.exists()) { setErrorMessage(newText + " doesn't exist"); setValid(false); return; } else if (dotFile.isDirectory()) { setErrorMessage(newText + " is a directory"); setValid(false); return; } else if (!GraphVizActivator.isExecutable(dotFile)) { setMessage(newText + " is not executable!", IMessageProvider.WARNING); } else if (!GraphVizActivator.DOT_FILE_NAME.equalsIgnoreCase(fileName)) { setMessage("The file name should be " + GraphVizActivator.DOT_FILE_NAME, IMessageProvider.WARNING); } } if (automaticDotButton.getSelection()) { if (!autodetectDotButton.isEnabled()) { setErrorMessage("No dot executable has been found"); } } setValid(true); } /** Returns the Dot search method that is currently in effect. * @return the method set in the prefs page * */ private DotMethod getCurrentDotMethod() { return GraphVizActivator.getInstance().getDotSearchMethod(); } /** * Return the dot algorithm positioned in the prefs page. * @return the current algo */ private DotAlgo getCurrentDotAlgo() { return GraphVizActivator.getInstance().getDotAlgo(); } /** * Scans the radio buttons and returns the dot method that the user has selected. * @return the currently selected dot search method */ private DotMethod getNewDotMethod() { if (useBundledDotButton.getSelection()) { return DotMethod.BUNDLE; } if (autodetectDotButton.getSelection()) { return DotMethod.DETECT; } if (specifyDotButton.getSelection()) { return DotMethod.MANUAL; } return DotMethod.AUTO; } /** * Scans the radio buttons and returns the dot method that the user has * selected. * @return the currently selected algorithm */ private DotAlgo getNewDotAlgo() { if (dotDotButton.getSelection()) { return DotAlgo.DOT; } if (neatoDotButton.getSelection()) { return DotAlgo.NEATO; } if (circoDotButton.getSelection()) { return DotAlgo.CIRCO; } if (fdpDotButton.getSelection()) { return DotAlgo.FDP; } // default to neato return DotAlgo.NEATO; } /** * {@inheritDoc} * @see IWorkbenchPreferencePage */ public void init(IWorkbench workbench) { } /** * The default button has been pressed. */ @Override protected final void performDefaults() { DotMethod dotMethod = DotMethod.AUTO; automaticDotButton.setSelection(dotMethod == DotMethod.AUTO); useBundledDotButton.setSelection(dotMethod == DotMethod.BUNDLE); autodetectDotButton.setSelection(dotMethod == DotMethod.DETECT); specifyDotButton.setSelection(dotMethod == DotMethod.MANUAL); dotBrowser.setText(""); DotAlgo dotAlgo = DotAlgo.NEATO; dotDotButton.setSelection(dotAlgo == DotAlgo.DOT); neatoDotButton.setSelection(dotAlgo == DotAlgo.NEATO); circoDotButton.setSelection(dotAlgo == DotAlgo.CIRCO); fdpDotButton.setSelection(dotAlgo == DotAlgo.FDP); super.performDefaults(); } /** * The user has pressed OK or Apply. Store this page's values. * @return true */ @Override public final boolean performOk() { GraphVizActivator graphviz = GraphVizActivator.getInstance(); graphviz.setDotSearchMethod(getNewDotMethod()); graphviz.setManualDotPath(dotBrowser.getText()); graphviz.setDotAlgo(getNewDotAlgo()); return true; } /** * Utility method that creates a radio button instance and sets the default layout data. * * @param parent the parent for the new button * @param label the label for the new button * @return the newly-created button */ private static Button createRadioButton(Composite parent, String label) { Button button = new Button(parent, SWT.RADIO | SWT.LEFT); button.setText(label); return button; } }