blob: 46790a9516e0855fcbd85f31a871bbb20a28c00e [file] [log] [blame]
package org.eclipse.jface.viewers;
/**********************************************************************
Copyright (c) 2000, 2002 International Business Machines Corp and others.
All rights reserved.   This program and the accompanying materials
are made available under the terms of the Common Public License v0.5
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/cpl-v05.html
 
Contributors:
**********************************************************************/
import java.text.MessageFormat;
import org.eclipse.jface.resource.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/**
* An abstract cell editor that uses a dialog.
* Dialog cell editors usually have a label control on the left and a button on
* the right. Pressing the button opens a dialog window (for example, a color dialog
* or a file dialog) to change the cell editor's value.
* The cell editor's value is the value of the dialog.
* <p>
* Subclasses may override the following method:
* <ul>
* <li><code>createButton</code>: creates the cell editor's button control</li>
* <li><code>openDialogBox</code>: opens the dialog box when the end user presses
* the button</li>
* <li><code>updateLabel</code>: updates the cell editor's label after its
* value has changed</li>
* </ul>
* </p>
*/
public abstract class DialogCellEditor extends CellEditor {
/**
* Image registry key for three dot image (value <code>"cell_editor_dots_button_image"</code>).
*/
public static final String CELL_EDITOR_IMG_DOTS_BUTTON = "cell_editor_dots_button_image";//$NON-NLS-1$
/**
* The editor control.
*/
private Composite editor;
/**
* The current contents.
*/
private Control contents;
/**
* The label that gets reused by <code>updateLabel</code>.
*/
private Label defaultLabel;
/**
* The button.
*/
private Button button;
/**
* The value of this cell editor; initially <code>null</code>.
*/
private Object value = null;
static {
ImageRegistry reg = JFaceResources.getImageRegistry();
reg.put(CELL_EDITOR_IMG_DOTS_BUTTON, ImageDescriptor.createFromFile(DialogCellEditor.class, "images/dots_button.gif"));//$NON-NLS-1$
}
/**
* Internal class for laying out the dialog.
*/
private class DialogCellLayout extends Layout {
public void layout(Composite editor, boolean force) {
Rectangle bounds = editor.getClientArea();
Point size = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, force);
if (contents != null)
contents.setBounds(0, 0, bounds.width-size.x, bounds.height);
button.setBounds(bounds.width-size.x, 0, size.x, bounds.height);
}
public Point computeSize(Composite editor, int wHint, int hHint, boolean force) {
if (wHint != SWT.DEFAULT && hHint != SWT.DEFAULT)
return new Point(wHint, hHint);
Point contentsSize = contents.computeSize(SWT.DEFAULT, SWT.DEFAULT, force);
Point buttonSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, force);
// Just return the button width to ensure the button is not clipped
// if the label is long.
// The label will just use whatever extra width there is
Point result = new Point(buttonSize.x,
Math.max(contentsSize.y, buttonSize.y));
return result;
}
}
/**
* Default DialogCellEditor style
*/
private static final int defaultStyle = SWT.NONE;
/**
* Creates a new dialog cell editor with no control
* @since 2.1
*/
public DialogCellEditor() {
setStyle(defaultStyle);
}
/**
* Creates a new dialog cell editor parented under the given control.
* The cell editor value is <code>null</code> initially, and has no
* validator.
*
* @param parent the parent control
*/
protected DialogCellEditor(Composite parent) {
this(parent, defaultStyle);
}
/**
* Creates a new dialog cell editor parented under the given control.
* The cell editor value is <code>null</code> initially, and has no
* validator.
*
* @param parent the parent control
* @param style the style bits
* @since 2.1
*/
protected DialogCellEditor(Composite parent, int style) {
super(parent, style);
}
/**
* Creates the button for this cell editor under the given parent control.
* <p>
* The default implementation of this framework method creates the button
* display on the right hand side of the dialog cell editor. Subclasses
* may extend or reimplement.
* </p>
*
* @param parent the parent control
* @return the new button control
*/
protected Button createButton(Composite parent) {
Button result = new Button(parent, SWT.DOWN);
result.setText("..."); //$NON-NLS-1$
return result;
}
/**
* Creates the controls used to show the value of this cell editor.
* <p>
* The default implementation of this framework method creates
* a label widget, using the same font and background color as the parent control.
* </p>
* <p>
* Subclasses may reimplement. If you reimplement this method, you
* should also reimplement <code>updateContents</code>.
* </p>
*
* @param cell the control for this cell editor
*/
protected Control createContents(Composite cell) {
defaultLabel = new Label(cell, SWT.LEFT);
defaultLabel.setFont(cell.getFont());
defaultLabel.setBackground(cell.getBackground());
return defaultLabel;
}
/* (non-Javadoc)
* Method declared on CellEditor.
*/
protected Control createControl(Composite parent) {
Font font = parent.getFont();
Color bg = parent.getBackground();
editor = new Composite(parent, getStyle());
editor.setFont(font);
editor.setBackground(bg);
editor.setLayout(new DialogCellLayout());
contents = createContents(editor);
updateContents(value);
button = createButton(editor);
button.setFont(font);
button.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
if (e.character == '\u001b') { // Escape
fireCancelEditor();
}
}
});
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
Object newValue = openDialogBox(editor);
if (newValue != null) {
boolean newValidState = isCorrect(newValue);
if (newValidState) {
markDirty();
doSetValue(newValue);
} else {
// try to insert the current value into the error message.
setErrorMessage(MessageFormat.format(getErrorMessage(), new Object[] { newValue.toString()}));
}
fireApplyEditorValue();
}
}
});
setValueValid(true);
return editor;
}
/* (non-Javadoc)
* Method declared on CellEditor.
*/
protected Object doGetValue() {
return value;
}
/* (non-Javadoc)
* Method declared on CellEditor.
* The focus is set to the cell editor's button.
*/
protected void doSetFocus() {
button.setFocus();
}
/* (non-Javadoc)
* Method declared on CellEditor.
*/
protected void doSetValue(Object value) {
this.value = value;
updateContents(value);
}
/**
* Returns the default label widget created by <code>createContents</code>.
*
* @return the default label widget
*/
protected Label getDefaultLabel() {
return defaultLabel;
}
/**
* Opens a dialog box under the given parent control and returns the
* dialog's value when it closes.
* <p>
* This framework method must be implemented by concrete subclasses.
* It is called when the user has pressed the button and the dialog
* box must pop up.
* </p>
*
* @param cellEditorWindow the parent control cell editor's window
* so that a subclass can adjust the dialog box accordingly
* @return the selected value
*/
protected abstract Object openDialogBox(Control cellEditorWindow);
/**
* Updates the controls showing the value of this cell editor.
* <p>
* The default implementation of this framework method just converts
* the passed object to a string using <code>toString</code> and
* sets this as the text of the label widget.
* </p>
* <p>
* Subclasses may reimplement. If you reimplement this method, you
* should also reimplement <code>createContents</code>.
* </p>
*
* @param value the new value of this cell editor
*/
protected void updateContents(Object value) {
if (defaultLabel == null)
return;
String text = "";//$NON-NLS-1$
if (value != null)
text = value.toString();
defaultLabel.setText(text);
}
}