/*
* $Id$
*
* Copyright (c) 2004-2005 by the TeXlapse Team.
* 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
*/
package net.sourceforge.texlipse.viewer;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import net.sourceforge.texlipse.TexlipsePlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
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.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
/**
* Viewer configuration editor.
* This dialog can be used for editing old configs or creating new ones.
*
* @author Kimmo Karlsson
* @author Tor Arne Vestb�
*/
public class ViewerConfigDialog extends Dialog {
private static final String[] inverseSearchValues = new String[] { ViewerAttributeRegistry.INVERSE_SEARCH_NO, ViewerAttributeRegistry.INVERSE_SEARCH_RUN, ViewerAttributeRegistry.INVERSE_SEARCH_STD };
protected File lastPath;
private Text fileField;
private Text nameField;
private Text argsField;
private DDEGroup ddeViewGroup;
private DDEGroup ddeCloseGroup;
private Combo formatChooser;
private Combo inverseChooser;
private Label statusField;
private ViewerAttributeRegistry registry;
private ArrayList nameList;
private boolean newConfig;
private Button forwardChoice;
/**
* Create a new config editor dialog.
* @param parentShell shell of the creating component
*/
public ViewerConfigDialog(Shell parentShell, ViewerAttributeRegistry reg) {
super(parentShell);
registry = reg;
newConfig = false;
}
/**
* Create a new config creator dialog.
* @param parentShell shell of the creating component
* @param nameList list of existing viewer configuration names
*/
public ViewerConfigDialog(Shell parentShell, ArrayList nameList) {
super(parentShell);
registry = new ViewerAttributeRegistry();
registry.setActiveViewer(ViewerAttributeRegistry.VIEWER_NONE);
this.nameList = nameList;
newConfig = true;
}
/**
* Set status field message.
* @param key message text key on resource bundle
* @param info value of the text parameter (%s)
*/
protected void setStatus(String key, String info) {
String msg = "";
if (key != null && key.length() > 0) {
msg = TexlipsePlugin.getResourceString(key);
if (msg.indexOf("%s") >= 0) {
msg = msg.replaceAll("%s", info);
}
}
statusField.setText(msg);
}
/**
* Set dialog title when the window is created.
*/
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
if (newConfig) {
newShell.setText(TexlipsePlugin.getResourceString("preferenceViewerDialogAddTitle"));
} else {
newShell.setText(TexlipsePlugin.getResourceString("preferenceViewerDialogEditTitle"));
}
}
/**
* Should be called after dialog has been closed.
* @return the viewer registry containing the dialog contents
*/
public ViewerAttributeRegistry getRegistry() {
return registry;
}
/**
* Check that the config is valid.
* Close the dialog is the config is valid.
*/
protected void okPressed() {
if (!validateFields())
return;
String name = nameField.getText();
registry.setActiveViewer(nameField.getText());
registry.setCommand(fileField.getText());
registry.setArguments(argsField.getText());
registry.setDDEViewCommand(ddeViewGroup.command.getText());
registry.setDDEViewServer(ddeViewGroup.server.getText());
registry.setDDEViewTopic(ddeViewGroup.topic.getText());
registry.setDDECloseCommand(ddeCloseGroup.command.getText());
registry.setDDECloseServer(ddeCloseGroup.server.getText());
registry.setDDECloseTopic(ddeCloseGroup.topic.getText());
registry.setFormat(formatChooser.getItem(formatChooser.getSelectionIndex()));
registry.setInverse(inverseSearchValues[inverseChooser.getSelectionIndex()]);
registry.setForward(forwardChoice.getSelection());
// Ask user if launch configs should be updated
try {
ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
if (manager != null) {
ILaunchConfigurationType type = manager.getLaunchConfigurationType(
TexLaunchConfigurationDelegate.CONFIGURATION_ID);
if (type != null) {
ILaunchConfiguration[] configs = manager.getLaunchConfigurations(type);
if (configs != null) {
// Check all configurations
int returnCode = 0;
MessageDialogWithToggle md = null;
for (int i = 0; i < configs.length ; i++) {
ILaunchConfiguration c = configs[i];
if (c.getType().getIdentifier().equals(TexLaunchConfigurationDelegate.CONFIGURATION_ID)) {
if (c.getAttribute("viewerCurrent", "").equals(name)) {
// We've found a config which was based on this viewer
if (0 == returnCode) {
String message = MessageFormat.format(
TexlipsePlugin.getResourceString("preferenceViewerUpdateConfigurationQuestion"),
new Object[] { c.getName() });
md = MessageDialogWithToggle.openYesNoCancelQuestion(getShell(),
TexlipsePlugin.getResourceString("preferenceViewerUpdateConfigurationTitle"), message,
TexlipsePlugin.getResourceString("preferenceViewerUpdateConfigurationAlwaysApply"),
false, null, null);
if (md.getReturnCode() == MessageDialogWithToggle.CANCEL)
return;
returnCode = md.getReturnCode();
}
// If answer was yes, update each config with latest values from registry
if (returnCode == IDialogConstants.YES_ID) {
ILaunchConfigurationWorkingCopy workingCopy = c.getWorkingCopy();
workingCopy.setAttributes(registry.asMap());
// We need to set at least one attribute using a one-shot setter method
// because the method setAttributes does not mark the config as dirty.
// A dirty config is required for a doSave to do anything useful.
workingCopy.setAttribute("viewerCurrent", name);
workingCopy.doSave();
}
// Reset return-code if we should be asked again
if (!md.getToggleState()) {
returnCode = 0;
}
}
}
}
}
}
}
} catch (CoreException e) {
// Something wrong with the config, or could not read attributes, so swallow and skip
}
setReturnCode(OK);
close();
}
/**
* Create the contents of the dialog.
* @param parent parent component
*/
protected Control createDialogArea(Composite parent) {
Composite composite = (Composite) super.createDialogArea(parent);
GridLayout gl = (GridLayout) composite.getLayout();
gl.numColumns = 2;
Label descrLabel = new Label(composite, SWT.LEFT);
descrLabel.setText(TexlipsePlugin.getResourceString("preferenceViewerDescriptionLabel"));
GridData dgd = new GridData(GridData.FILL_HORIZONTAL);
dgd.horizontalSpan = 2;
descrLabel.setLayoutData(dgd);
addConfigNameField(composite);
addFileBrowser(composite);
addArgumentsField(composite);
addDDEGroups(composite);
addFormatChooser(composite);
addInverseChooser(composite);
addForwardChooser(composite);
Group group = new Group(composite, SWT.SHADOW_IN);
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
((GridData)group.getLayoutData()).horizontalSpan = 2;
group.setLayout(new GridLayout());
statusField = new Label(group, SWT.LEFT);
statusField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
statusField.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerStatusTooltip"));
return composite;
}
/*
* @see org.eclipse.jface.dialogs.Dialog#createButtonBar(org.eclipse.swt.widgets.Composite)
*/
protected Control createButtonBar(Composite parent) {
Control ctrl = super.createButtonBar(parent);
validateFields();
return ctrl;
}
private boolean validateFields() {
boolean everythingOK = true;
String name = nameField.getText();
if ( nameField.getText() == null || nameField.getText().length() == 0) {
setStatus("preferenceViewerDialogNameEmpty", "");
everythingOK = false;
}
if (formatChooser.getSelectionIndex() == -1) {
setStatus("preferenceViewerFormatEmpty", "");
everythingOK = false;
}
// if adding new configuration, existing name is not valid
if (nameList != null && nameList.contains(name)) {
setStatus("preferenceViewerDialogNameExists", name);
everythingOK = false;
}
File f = new File(fileField.getText());
if (fileField.getText().trim().equals("")) {
setStatus("preferenceViewerDialogFileNoFile", "");
everythingOK = false;
}
else if (!f.exists()) {
setStatus("preferenceViewerDialogFileNotFound", "");
everythingOK = false;
}
if (!everythingOK) {
Button b = getButton(IDialogConstants.OK_ID);
if (b != null) {
// set button status
b.setEnabled(false);
}
return false;
}
Button b = getButton(IDialogConstants.OK_ID);
if (b != null) {
b.setEnabled(true);
}
setStatus("preferenceViewerDialogFileOk", "");
return true;
}
/**
* Creates the configuration name text field.
* @param composite parent component
*/
private void addConfigNameField(Composite composite) {
Label nameLabel = new Label(composite, SWT.LEFT);
nameLabel.setText(TexlipsePlugin.getResourceString("preferenceViewerNameLabel"));
nameLabel.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerNameTooltip"));
nameLabel.setLayoutData(new GridData());
int rw = newConfig ? 0 : SWT.READ_ONLY;
nameField = new Text(composite, SWT.SINGLE | SWT.BORDER | rw);
nameField.setText(registry.getActiveViewer());
nameField.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerNameTooltip"));
nameField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
}
/**
* Creates the executable browsing component.
* @param composite parent component
*/
private void addFileBrowser(Composite composite) {
Label fileLabel = new Label(composite, SWT.LEFT);
fileLabel.setText(TexlipsePlugin.getResourceString("preferenceViewerCommandLabel"));
fileLabel.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerCommandTooltip"));
fileLabel.setLayoutData(new GridData());
Composite browser = new Composite(composite, SWT.NONE);
browser.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
GridLayout bgl = new GridLayout();
bgl.numColumns = 2;
browser.setLayout(bgl);
fileField = new Text(browser, SWT.SINGLE | SWT.BORDER);
fileField.setText(registry.getCommand());
fileField.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerCommandTooltip"));
fileField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fileField.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
validateFields();
}});
Button browseButton = new Button(browser, SWT.PUSH);
browseButton.setText(JFaceResources.getString("openBrowse"));
browseButton.setLayoutData(new GridData());
browseButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
FileDialog dialog = new FileDialog(getShell());
if (lastPath != null) {
if (lastPath.exists()) {
dialog.setFilterPath(lastPath.getAbsolutePath());
}
} else {
lastPath = new File(fileField.getText());
while (lastPath != null && !lastPath.isDirectory()) {
lastPath = lastPath.getParentFile();
}
if (lastPath != null && lastPath.exists()) {
dialog.setFilterPath(lastPath.getAbsolutePath());
}
}
String dir = dialog.open();
if (dir != null) {
lastPath = new File(dir.trim());
if (lastPath.exists()) {
fileField.setText(lastPath.getAbsolutePath());
registry.setCommand(fileField.getText());
} else {
lastPath = null;
}
}
}});
}
/**
* Creates the command arguments field to the dialog.
* @param composite parent component
*/
private void addArgumentsField(Composite composite) {
Label argsLabel = new Label(composite, SWT.LEFT);
argsLabel.setText(TexlipsePlugin.getResourceString("preferenceViewerArgumentLabel"));
argsLabel.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerArgumentTooltip"));
argsLabel.setLayoutData(new GridData());
argsField = new Text(composite, SWT.SINGLE | SWT.BORDER);
argsField.setText(registry.getArguments());
argsField.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerArgumentTooltip"));
argsField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
}
/**
* Creates the two groups for DDE view and close
*
* @param composite
* parent component
*/
private void addDDEGroups(Composite composite) {
ddeViewGroup = new DDEGroup(composite,
TexlipsePlugin.getResourceString("preferenceViewerDDEViewLabel"),
TexlipsePlugin.getResourceString("preferenceViewerDDEViewTooltip"));
ddeViewGroup.command.setText(registry.getDDEViewCommand());
ddeViewGroup.server.setText(registry.getDDEViewServer());
ddeViewGroup.topic.setText(registry.getDDEViewTopic());
ddeCloseGroup = new DDEGroup(composite,
TexlipsePlugin.getResourceString("preferenceViewerDDECloseLabel"),
TexlipsePlugin.getResourceString("preferenceViewerDDECloseTooltip"));
ddeCloseGroup.command.setText(registry.getDDECloseCommand());
ddeCloseGroup.server.setText(registry.getDDECloseServer());
ddeCloseGroup.topic.setText(registry.getDDECloseTopic());
// Only show DDE configuration if on Win32
if (Platform.getOS().equals(Platform.OS_WIN32)) {
ddeViewGroup.setVisible(true);
ddeCloseGroup.setVisible(true);
}
}
/**
* Creates the file format chooser to the page.
* @param composite parent component
*/
private void addFormatChooser(Composite composite) {
Label formatLabel = new Label(composite, SWT.LEFT);
formatLabel.setText(TexlipsePlugin.getResourceString("preferenceViewerFormatLabel"));
formatLabel.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerFormatTooltip"));
formatLabel.setLayoutData(new GridData());
formatChooser = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY);
formatChooser.setLayoutData(new GridData());
formatChooser.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerFormatTooltip"));
formatChooser.setItems(registry.getFormatList());
formatChooser.select(formatChooser.indexOf(registry.getFormat()));
}
/**
* Creates the additional controls of the page.
* @param parent parent component
*/
private void addInverseChooser(Composite parent) {
Label label = new Label(parent, SWT.LEFT);
label.setText(TexlipsePlugin.getResourceString("preferenceViewerInverseLabel"));
label.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerInverseTooltip"));
label.setLayoutData(new GridData());
String[] list = new String[] {
TexlipsePlugin.getResourceString("preferenceViewerInverseSearchNo"),
TexlipsePlugin.getResourceString("preferenceViewerInverseSearchRun"),
TexlipsePlugin.getResourceString("preferenceViewerInverseSearchStd")
};
// find out which option to choose by default
int index = inverseSearchValues.length - 1;
for (; index > 0 && !inverseSearchValues[index].equals(registry.getInverse()); index--) {}
inverseChooser = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
inverseChooser.setLayoutData(new GridData());
inverseChooser.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerInverseTooltip"));
inverseChooser.setItems(list);
inverseChooser.select(index);
}
/**
* Creates the forward search support -checkbox.
* @param parent parent component
*/
private void addForwardChooser(Composite parent) {
forwardChoice = new Button(parent, SWT.CHECK);
forwardChoice.setText(TexlipsePlugin.getResourceString("preferenceViewerForwardLabel"));
GridData gd = new GridData();
gd.horizontalSpan = 2;
forwardChoice.setLayoutData(gd);
forwardChoice.setSelection(registry.getForward());
}
private class DDEGroup extends Composite {
// Public members since the class is private to the dialog
public Text command;
public Text server;
public Text topic;
public DDEGroup(Composite parent, String name, String toolTip) {
super(parent, SWT.NONE);
setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
((GridData)getLayoutData()).horizontalSpan = 2;
setLayout( new GridLayout());
Group group = new Group(this, SWT.SHADOW_IN);
group.setText(name);
group.setToolTipText(toolTip);
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
group.setLayout(new GridLayout(4, false));
Label ddeCommandLabel = new Label(group, SWT.LEFT);
ddeCommandLabel.setText(TexlipsePlugin.getResourceString("preferenceViewerDDECommandLabel"));
ddeCommandLabel.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerDDECommandTooltip"));
ddeCommandLabel.setLayoutData(new GridData());
command = new Text(group, SWT.SINGLE | SWT.BORDER);
command.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerDDECommandTooltip"));
command.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
((GridData) command.getLayoutData()).horizontalSpan = 3;
Label ddeServerLabel = new Label(group, SWT.LEFT);
ddeServerLabel.setText(TexlipsePlugin.getResourceString("preferenceViewerDDEServerLabel"));
ddeServerLabel.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerDDEServerTooltip"));
ddeServerLabel.setLayoutData(new GridData());
server = new Text(group, SWT.SINGLE | SWT.BORDER);
server.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerDDEServerTooltip"));
server.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Label ddeTopicLabel = new Label(group, SWT.LEFT);
ddeTopicLabel.setText(TexlipsePlugin.getResourceString("preferenceViewerDDETopicLabel"));
ddeTopicLabel.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerDDETopicTooltip"));
ddeTopicLabel.setLayoutData(new GridData());
topic = new Text(group, SWT.SINGLE | SWT.BORDER);
topic.setToolTipText(TexlipsePlugin.getResourceString("preferenceViewerDDETopicTooltip"));
topic.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
setVisible(false);
}
}
}