blob: 4f7c26bde8efd92fae37904b156794899d0f8660 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 Code 9 Corporation and others.
* 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:
* Code 9 Corporation - initial API and implementation
* Chris Aniszczyk <caniszczyk@gmail.com>
* Rafael Oliveira Nobrega <rafael.oliveira@gmail.com> - bug 242028
*******************************************************************************/
package org.eclipse.pde.internal.ds.ui.parts;
import org.eclipse.pde.internal.ds.ui.editor.FormLayoutFactory;
import org.eclipse.swt.SWT;
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.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.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.IFormColors;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.forms.widgets.TableWrapData;
import org.eclipse.ui.forms.widgets.TableWrapLayout;
/**
* The helper class for creating entry fields with label and text.
* Optionally, a button can be added after the text. The attached listener
* reacts to all the events. Entring new text makes the entry 'dirty', but
* only when 'commit' is called is 'valueChanged' method called (and only if
* 'dirty' flag is set). This allows delayed commit.
*/
public class FormEntry {
private Control fLabel;
private Text fText;
private Button fBrowse;
private String fValue = ""; //$NON-NLS-1$
private boolean fDirty;
boolean fIgnoreModify = false;
private IFormEntryListener fListener;
public static final int F_DEFAULT_TEXT_WIDTH_HINT = 100;
/**
* The default constructor. Call 'createControl' to make it.
*
*/
public FormEntry(Composite parent, FormToolkit toolkit, String labelText,
int style) {
createControl(parent, toolkit, labelText, style, null, false, 0, 0);
}
/**
* This constructor create all the controls right away.
*
* @param parent
* @param toolkit
* @param labelText
* @param browseText
* @param linkLabel
*/
public FormEntry(Composite parent, FormToolkit toolkit, String labelText,
String browseText, boolean linkLabel) {
this(parent, toolkit, labelText, browseText, linkLabel, 0);
}
public FormEntry(Composite parent, FormToolkit toolkit, String labelText,
String browseText, boolean linkLabel, int indent) {
createControl(parent, toolkit, labelText, SWT.SINGLE, browseText,
linkLabel, indent, 0);
}
public FormEntry(Composite parent, FormToolkit toolkit, String labelText,
int indent, int tcolspan) {
createControl(parent, toolkit, labelText, SWT.SINGLE, null, false,
indent, tcolspan);
}
/**
* Create all the controls in the provided parent.
*
* @param parent
* @param toolkit
* @param labelText
* @param span
* @param browseText
* @param linkLabel
*/
private void createControl(Composite parent, FormToolkit toolkit,
String labelText, int style, String browseText, boolean linkLabel,
int indent, int tcolspan) {
if (linkLabel) {
Hyperlink link = toolkit.createHyperlink(parent, labelText,
SWT.NULL);
fLabel = link;
} else {
if (labelText != null) {
fLabel = toolkit.createLabel(parent, labelText);
fLabel.setForeground(toolkit.getColors().getColor(
IFormColors.TITLE));
}
}
fText = toolkit.createText(parent, "", style); //$NON-NLS-1$
addListeners();
if (browseText != null) {
fBrowse = toolkit.createButton(parent, browseText, SWT.PUSH);
fBrowse.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
if (fListener != null)
fListener.browseButtonSelected(FormEntry.this);
}
});
}
fillIntoGrid(parent, indent, tcolspan);
// Set the default text width hint and let clients modify
// accordingly
// after the fact
setTextWidthHint(F_DEFAULT_TEXT_WIDTH_HINT);
}
public void setEditable(boolean editable) {
fText.setEditable(editable);
if (fLabel instanceof Hyperlink)
((Hyperlink) fLabel).setUnderlined(editable);
if (fBrowse != null)
fBrowse.setEnabled(editable);
}
private void fillIntoGrid(Composite parent, int indent, int tcolspan) {
Layout layout = parent.getLayout();
int tspan;
if (layout instanceof GridLayout) {
int span = ((GridLayout) layout).numColumns;
if (tcolspan > 0)
tspan = tcolspan;
else
tspan = fBrowse != null ? span - 2 : span - 1;
GridData gd;
if (fLabel != null) {
gd = new GridData(GridData.VERTICAL_ALIGN_CENTER);
gd.horizontalIndent = indent;
fLabel.setLayoutData(gd);
}
gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
gd.horizontalSpan = tspan;
if (fLabel != null) {
gd.horizontalIndent = FormLayoutFactory.CONTROL_HORIZONTAL_INDENT;
}
gd.grabExcessHorizontalSpace = (tspan == 1);
gd.widthHint = 10;
fText.setLayoutData(gd);
if (fBrowse != null) {
gd = new GridData(GridData.VERTICAL_ALIGN_CENTER);
fBrowse.setLayoutData(gd);
}
} else if (layout instanceof TableWrapLayout) {
int span = ((TableWrapLayout) layout).numColumns;
if (tcolspan > 0)
tspan = tcolspan;
else
tspan = fBrowse != null ? span - 2 : span - 1;
TableWrapData td;
if (fLabel != null) {
td = new TableWrapData();
td.valign = TableWrapData.MIDDLE;
td.indent = indent;
fLabel.setLayoutData(td);
}
td = new TableWrapData(TableWrapData.FILL);
td.colspan = tspan;
if (fLabel != null) {
td.indent = FormLayoutFactory.CONTROL_HORIZONTAL_INDENT;
}
td.grabHorizontal = (tspan == 1);
td.valign = TableWrapData.MIDDLE;
fText.setLayoutData(td);
if (fBrowse != null) {
td = new TableWrapData(TableWrapData.FILL);
td.valign = TableWrapData.MIDDLE;
fBrowse.setLayoutData(td);
}
}
}
/**
* Attaches the listener for the entry.
*
* @param listener
*/
public void setFormEntryListener(IFormEntryListener listener) {
if (fLabel != null && fLabel instanceof Hyperlink) {
if (this.fListener != null)
((Hyperlink) fLabel).removeHyperlinkListener(this.fListener);
if (listener != null)
((Hyperlink) fLabel).addHyperlinkListener(listener);
}
this.fListener = listener;
}
private void addListeners() {
fText.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
keyReleaseOccured(e);
}
});
fText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
editOccured(e);
}
});
fText.addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
if (fListener != null)
fListener.focusGained(FormEntry.this);
}
public void focusLost(FocusEvent e) {
if (fDirty)
commit();
}
});
}
/**
* If dirty, commits the text in the widget to the value and notifies
* the listener. This call clears the 'dirty' flag.
*
*/
public void commit() {
if (fDirty) {
fValue = fText.getText();
// if (value.length()==0)
// value = null;
// notify
if (fListener != null)
fListener.textValueChanged(this);
}
fDirty = false;
}
public void cancelEdit() {
fDirty = false;
}
private void editOccured(ModifyEvent e) {
if (fIgnoreModify)
return;
fDirty = true;
if (fListener != null)
fListener.textDirty(this);
}
/**
* Returns the text control.
*
* @return
*/
public Text getText() {
return fText;
}
public Control getLabel() {
return fLabel;
}
/**
* Returns the browse button control.
*
* @return
*/
public Button getButton() {
return fBrowse;
}
/**
* Returns the current entry value. If the entry is dirty and was not
* commited, the value may be different from the text in the widget.
*
* @return
*/
public String getValue() {
return fValue.trim();
}
/**
* Returns true if the text has been modified.
*
* @return
*/
public boolean isDirty() {
return fDirty;
}
private void keyReleaseOccured(KeyEvent e) {
if (e.character == '\r') {
// commit value
if (fDirty)
commit();
} else if (e.character == '\u001b') { // Escape character
if (!fValue.equals(fText.getText()))
fText.setText(fValue != null ? fValue : ""); // //$NON-NLS-1$
// restore
// old
fDirty = false;
}
if (fListener != null)
fListener.selectionChanged(FormEntry.this);
}
/**
* Sets the value of this entry.
*
* @param value
*/
public void setValue(String value) {
if (fText != null)
fText.setText(value != null ? value : ""); //$NON-NLS-1$
this.fValue = (value != null) ? value : ""; //$NON-NLS-1$
}
/**
* Sets the value of this entry with the possibility to turn the
* notification off.
*
* @param value
* @param blockNotification
*/
public void setValue(String value, boolean blockNotification) {
fIgnoreModify = blockNotification;
setValue(value);
fIgnoreModify = false;
}
public void setVisible(boolean visible) {
if (fLabel != null)
fLabel.setVisible(visible);
if (fText != null)
fText.setVisible(visible);
if (fBrowse != null)
fBrowse.setVisible(visible);
}
/**
* If GridData was used, set the width hint. If TableWrapData was used
* set the max width. If no layout data was specified, this method does
* nothing.
*
* @param width
*/
public void setTextWidthHint(int width) {
Object data = getText().getLayoutData();
if (data == null) {
return;
} else if (data instanceof GridData) {
((GridData) data).widthHint = width;
} else if (data instanceof TableWrapData) {
((TableWrapData) data).maxWidth = width;
}
}
}