/******************************************************************************* * Copyright (c) 2008 Scott Stanchfield, based on ANTLR-Eclipse plugin * by Torsten Juergeleit. * 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 * Torsten Juergeleit - original ANTLR Eclipse plugin * Scott Stanchfield - modifications for ANTXR *******************************************************************************/ package com.javadude.antxr.eclipse.ui.properties; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; 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.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; import org.eclipse.ui.dialogs.ISelectionStatusValidator; import org.eclipse.ui.dialogs.PropertyPage; import org.eclipse.ui.model.WorkbenchContentProvider; import org.eclipse.ui.model.WorkbenchLabelProvider; import com.javadude.antxr.eclipse.core.AntxrCorePlugin; import com.javadude.antxr.eclipse.core.properties.SettingsPersister; import com.javadude.antxr.eclipse.ui.AntxrUIPlugin; /** * Properties page for ANTXR grammar files. * It appends the name of the according grammar file to the file name. */ public class GrammarPropertyPage extends PropertyPage { // TODO cleanup the layout of this pref page! // TODO figure out how to force a rebuild when the user changes options! // TODO store prefs in an xml file called .antxr so they can be shared private static final String PREFIX = "Properties.Grammar."; private Map<String, Map<String, String>> map; private Text fOutputText; private Text fGrammarText; private Map<String, Button> booleanControls = new HashMap<String, Button>(); private Map<String, Boolean> booleanDefaults = new HashMap<String, Boolean>(); /* (non-Javadoc) * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite) */ protected Control createContents(Composite aParent) { Composite composite = setupGridLayout(new Composite(aParent, SWT.NONE)); // TODO remove the following if we can force a rebuild like jdt does when java options change Label note = new Label(composite, SWT.NONE); note.setText("Note: You must recompile your grammar for these changes to take place"); // read the settings for this grammar map = SettingsPersister.readSettings(((IResource)getElement()).getProject()); AntxrCorePlugin.getDefault().upgradeOldSettings((IResource)getElement(), map); addOutputProperty(composite); addGrammarProperty(composite); addBooleanProperty(SWT.CHECK, SettingsPersister.SMAP_PROPERTY, getString("smap.label"), composite, true); addBooleanProperty(SWT.CHECK, SettingsPersister.DEBUG_PROPERTY, getString("debug.label"), composite, false); Group outputType = (Group)setupGridLayout(new Group(composite, SWT.SHADOW_ETCHED_IN)); outputType.setText(getString("output.types.label")); addBooleanProperty(SWT.RADIO, SettingsPersister.NORMAL_PROPERTY, getString("normal.label"), outputType, true); addBooleanProperty(SWT.RADIO, SettingsPersister.HTML_PROPERTY, getString("html.label"), outputType, false); addBooleanProperty(SWT.RADIO, SettingsPersister.DOCBOOK_PROPERTY, getString("docbook.label"), outputType, false); addBooleanProperty(SWT.RADIO, SettingsPersister.DIAGNOSTIC_PROPERTY, getString("diagnostic.label"), outputType, false); Group traceType = (Group)setupGridLayout(new Group(composite, SWT.SHADOW_ETCHED_IN)); traceType.setText(getString("trace.types.label")); addBooleanProperty(SWT.RADIO, SettingsPersister.NOTRACE_PROPERTY, getString("notrace.label"), traceType, true); addBooleanProperty(SWT.RADIO, SettingsPersister.TRACE_PROPERTY, getString("trace.label"), traceType, false); addBooleanProperty(SWT.RADIO, SettingsPersister.TRACE_PARSER_PROPERTY, getString("traceParser.label"), traceType, false); addBooleanProperty(SWT.RADIO, SettingsPersister.TRACE_LEXER_PROPERTY, getString("traceLexer.label"), traceType, false); addBooleanProperty(SWT.RADIO, SettingsPersister.TRACE_TREE_PARSER_PROPERTY, getString("traceTreeParser.label"), traceType, false); return composite; } private Composite setupGridLayout(Composite composite) { GridLayout layout = new GridLayout(); composite.setLayout(layout); GridData data = new GridData(GridData.FILL); data.grabExcessHorizontalSpace = true; composite.setLayoutData(data); return composite; } private void addOutputProperty(Composite aParent) { Composite composite = createDefaultComposite(aParent); // Label for output field Label label = new Label(composite, SWT.NONE); label.setText(getString("output.label")); // label.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); // Output text field fOutputText = new Text(composite, SWT.READ_ONLY | SWT.SINGLE | SWT.BORDER); String output = SettingsPersister.get(map, (IResource)getElement(), SettingsPersister.OUTPUT_PROPERTY); if (output != null) { fOutputText.setText(output); } GridData gd = new GridData(); gd.horizontalAlignment= GridData.FILL_HORIZONTAL; gd.widthHint = convertWidthInCharsToPixels(50); // gd.grabExcessHorizontalSpace = true; fOutputText.setLayoutData(gd); // Choose folder button Button button = new Button(composite, SWT.PUSH); button.setText(getString("output.button")); button.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent anEvent) { chooseOutputFolder(); } public void widgetSelected(SelectionEvent anEvent) { chooseOutputFolder(); } }); } private void addGrammarProperty(Composite aParent) { Composite composite = createDefaultComposite(aParent); // Label for grammar field Label label = new Label(composite, SWT.NONE); label.setText(getString("grammar.label")); // Grammar text field fGrammarText = new Text(composite, SWT.READ_ONLY | SWT.SINGLE | SWT.BORDER); String grammar; grammar = SettingsPersister.get(map, (IResource)getElement(), SettingsPersister.SUPER_GRAMMARS_PROPERTY); if (grammar != null) { fGrammarText.setText(grammar); } GridData gd = new GridData(); gd.horizontalAlignment= GridData.FILL_HORIZONTAL; gd.widthHint = convertWidthInCharsToPixels(50); // gd.grabExcessHorizontalSpace = true; fGrammarText.setLayoutData(gd); // Choose folder button Button button = new Button(composite, SWT.PUSH); button.setText(getString("grammar.button")); button.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent anEvent) { chooseGrammarFile(); } public void widgetSelected(SelectionEvent anEvent) { chooseGrammarFile(); } }); } private void addBooleanProperty(int type, final String propertyName, String label, Composite aParent, boolean defaultValue) { // Label for grammar field final Button button = new Button(aParent, type); booleanControls.put(propertyName, button); booleanDefaults.put(propertyName, Boolean.valueOf(defaultValue)); button.setText(label); String value = SettingsPersister.get(map, (IResource)getElement(), propertyName); boolean booleanValue; if (value == null) { booleanValue = defaultValue; SettingsPersister.set(map, (IResource)getElement(), propertyName,defaultValue?"true":"false"); } else { booleanValue = ("true".equalsIgnoreCase(value)); } button.setSelection(booleanValue); } private Composite createDefaultComposite(Composite aParent) { Composite composite = new Composite(aParent, SWT.NULL); GridLayout layout = new GridLayout(); layout.numColumns = 3; composite.setLayout(layout); GridData data = new GridData(); data.verticalAlignment = GridData.FILL; data.horizontalAlignment = GridData.FILL; composite.setLayoutData(data); return composite; } /** {@inheritDoc} */ public boolean performOk() { SettingsPersister.set(map, (IResource)getElement(), SettingsPersister.OUTPUT_PROPERTY, fOutputText.getText()); SettingsPersister.set(map, (IResource)getElement(), SettingsPersister.SUPER_GRAMMARS_PROPERTY, fGrammarText.getText()); for (Iterator i = booleanControls.keySet().iterator(); i.hasNext();) { String propertyName = (String)i.next(); Button b = booleanControls.get(propertyName); SettingsPersister.set(map, (IResource)getElement(), propertyName, String.valueOf(b.getSelection())); } SettingsPersister.writeSettings(((IResource)getElement()).getProject(), map); return true; } /* (non-Javadoc) * @see org.eclipse.jface.preference.PreferencePage#performDefaults() */ protected void performDefaults() { fOutputText.setText(""); fGrammarText.setText(""); for (Iterator i = booleanControls.keySet().iterator(); i.hasNext();) { QualifiedName propertyName = (QualifiedName)i.next(); Button b = booleanControls.get(propertyName); Boolean defaultValue = booleanDefaults.get(propertyName); b.setSelection(defaultValue.booleanValue()); } } private String getString(String aKey) { return AntxrUIPlugin.getMessage(GrammarPropertyPage.PREFIX + aKey); } private void chooseOutputFolder() { ISelectionStatusValidator validator = new ISelectionStatusValidator() { public IStatus validate(Object[] aSelection) { for (int i= 0; i < aSelection.length; i++) { if (!(aSelection[i] instanceof IFolder || aSelection[i] instanceof IProject)) { return new Status(IStatus.ERROR, AntxrUIPlugin.getUniqueIdentifier(), IStatus.OK, getString("output.choose.select"), null); } } return new Status(IStatus.OK, AntxrUIPlugin.getUniqueIdentifier(), IStatus.OK, "", null); } }; ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog( getShell(), new WorkbenchLabelProvider(), new WorkbenchContentProvider()); dialog.setValidator(validator); dialog.setTitle(getString("output.choose.title")); dialog.setMessage(getString("output.choose.message")); dialog.addFilter(new FolderFilter()); dialog.setInput(ResourcesPlugin.getWorkspace().getRoot()); dialog.setAllowMultiple(false); if (dialog.open() == Window.OK) { Object[] folders = dialog.getResult(); String folder; if (folders.length > 0) { folder = ((IResource)folders[0]).getFullPath().toString(); } else { folder = ""; } fOutputText.setText(folder); } } private static class FolderFilter extends ViewerFilter { /** {@inheritDoc} */ public boolean select(Viewer aViewer, Object aParent, Object anElement) { return ((anElement instanceof IProject && ((IProject)anElement).isOpen()) || anElement instanceof IFolder); } } private void chooseGrammarFile() { ISelectionStatusValidator validator = new ISelectionStatusValidator() { public IStatus validate(Object[] aSelection) { for (int i= 0; i < aSelection.length; i++) { if (!(aSelection[i] instanceof IFile)) { return new Status(IStatus.ERROR, AntxrUIPlugin.getUniqueIdentifier(), IStatus.OK, getString("grammar.choose.select"), null); } } return new Status(IStatus.OK, AntxrUIPlugin.getUniqueIdentifier(), IStatus.OK, "", null); } }; ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog( getShell(), new WorkbenchLabelProvider(), new WorkbenchContentProvider()); dialog.setValidator(validator); dialog.setTitle(getString("grammar.choose.title")); dialog.setMessage(getString("grammar.choose.message")); dialog.addFilter(new GrammarFileFilter()); dialog.setInput(ResourcesPlugin.getWorkspace().getRoot()); dialog.setAllowMultiple(true); if (dialog.open() == Window.OK) { Object[] files = dialog.getResult(); // Create list of grammars delimited by ';' StringBuffer grammars = new StringBuffer(); for (int i = 0; i < files.length; i++) { grammars.append(((IFile)files[i]).getFullPath().toString()); if (i < (files.length - 1)) { grammars.append(';'); } } fGrammarText.setText(grammars.toString()); } } private static class GrammarFileFilter extends ViewerFilter { /** {@inheritDoc} */ public boolean select(Viewer aViewer, Object aParent, Object anElement) { boolean select = false; if (anElement instanceof IProject || anElement instanceof IFolder) { select = true; } else if (anElement instanceof IFile) { String extension = ((IFile)anElement).getFileExtension(); if (extension != null && extension.equals("g")) { select = true; } } return select; } } }