blob: 5ba09c2e4c8fa70fa297033eeb20d56da097de3d [file] [log] [blame]
package org.eclipse.debug.internal.ui;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.util.Iterator;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IValueModification;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TreeEditor;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.actions.SelectionProviderAction;
/**
* Action for changing the value of primitives and <code>String</code> variables.
*/
public class ChangeVariableValueAction extends SelectionProviderAction {
// Fields for inline editing
protected Composite fComposite;
protected Tree fTree;
protected Label fEditorLabel;
protected Text fEditorText;
protected TreeEditor fTreeEditor;
protected IVariable fVariable;
private static final String PREFIX= "change_variable_value_action.";
private static final String ERROR= PREFIX + "error.";
private static final String DIALOG_TITLE= PREFIX + "dialog.title";
private static final String DIALOG_MESSAGE= PREFIX + "dialog.message";
private static final String DIALOG_INVALID= PREFIX + "dialog.invalid";
public ChangeVariableValueAction(Viewer viewer) {
super(viewer, DebugUIUtils.getResourceString(PREFIX + TEXT));
setDescription(DebugUIUtils.getResourceString(PREFIX + DESCRIPTION));
fTree= ((TreeViewer)viewer).getTree();
fTreeEditor= new TreeEditor(fTree);
}
/**
* Edit the variable value with an inline text editor.
*/
protected void doActionPerformed(final IVariable variable) {
final Shell activeShell= DebugUIPlugin.getActiveWorkbenchWindow().getShell();
// If a previous edit is still in progress, finish it
if (fEditorText != null) {
saveChangesAndCleanup(fVariable, activeShell);
}
fVariable = variable;
// Use a Composite containing a Label and a Text. This allows us to edit just
// the value, while still showing the variable name.
fComposite = new Composite(fTree, SWT.NONE);
fComposite.setBackground(fTree.getBackground());
GridLayout layout = new GridLayout();
layout.numColumns = 2;
layout.marginHeight = 0;
layout.marginWidth = 0;
fComposite.setLayout(layout);
fEditorLabel = new Label(fComposite, SWT.LEFT);
fEditorLabel.setLayoutData(new GridData(GridData.FILL_VERTICAL));
fEditorText = new Text(fComposite, SWT.BORDER | SWT.SINGLE | SWT.LEFT);
fEditorText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
String valueString= "";
try {
valueString= fVariable.getValue().getValueString();
} catch (DebugException de) {
DebugUIUtils.errorDialog(activeShell, ERROR, de.getStatus());
}
TreeItem[] selectedItems = fTree.getSelection();
fTreeEditor.horizontalAlignment = SWT.LEFT;
fTreeEditor.grabHorizontal = true;
fTreeEditor.setEditor(fComposite, selectedItems[0]);
// This is a hack. There is no API on model presentation to get just the
// variable name, so we have to make do with just calling IVariable.getName()
String varName = "";
try {
varName = fVariable.getName();
} catch (DebugException de) {
}
fEditorLabel.setText(varName + "=");
fEditorText.setText(valueString);
fEditorText.selectAll();
fComposite.layout(true);
fComposite.setVisible(true);
fEditorText.setFocus();
// CR means commit the change, ESC means abort changing the value
fEditorText.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent event) {
if (event.character == SWT.CR) {
saveChangesAndCleanup(fVariable, activeShell);
}
if (event.character == SWT.ESC) {
cleanup();
}
}
});
// If the focus is lost, then act as if user hit CR and commit change
fEditorText.addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent fe) {
saveChangesAndCleanup(fVariable, activeShell);
}
});
}
/**
* If the new value validates, save it, and dispose the text widget,
* otherwise sound the system bell and leave the user in the editor.
*/
protected void saveChangesAndCleanup(IVariable variable, Shell shell) {
String newValue= fEditorText.getText();
try {
if (!variable.verifyValue(newValue)) {
shell.getDisplay().beep();
return;
}
variable.setValue(newValue);
} catch (DebugException de) {
DebugUIUtils.errorDialog(shell, ERROR, de.getStatus());
}
cleanup();
}
/**
* Tidy up the widgets that were used
*/
private void cleanup() {
if (fEditorText != null) {
fEditorText.dispose();
fEditorText = null;
fVariable = null;
fTreeEditor.setEditor(null, null);
fComposite.setVisible(false);
}
}
/**
* Updates the enabled state of this action based
* on the selection
*/
protected void update(IStructuredSelection sel) {
Iterator iter= sel.iterator();
if (iter.hasNext()) {
Object object= iter.next();
if (object instanceof IValueModification) {
IValueModification varMod= (IValueModification)object;
if (!varMod.supportsValueModification()) {
setEnabled(false);
return;
}
setEnabled(!iter.hasNext());
return;
}
}
setEnabled(false);
}
/**
* @see Action
*/
public void run() {
Iterator iterator= getStructuredSelection().iterator();
doActionPerformed((IVariable)iterator.next());
}
/**
* @see SelectionProviderAction
*/
public void selectionChanged(IStructuredSelection sel) {
update(sel);
}
}