Bug 74337 FieldEditor should document that doFillIntoGrid() is called from the superclass constructor.
The doFillIntoGrid() method is called from the constructor of the FieldEditor class. This should REALLY be documented. It cost me 3 hours of work on a nasty bug. Consider the following addition to the documentation: --------------------------------------------------------------------------- <p> Developers should be aware that FieldEditor calls the doFillIntoGrid() method in its constructor. The significance of this can be demonstrated by the following snippet. </p> <pre> public class RegexPatternSetFieldEditor extends FieldEditor implements SelectionListener,IDoubleClickListener { // .... snip /** The sorted set of patterns. */ private final SortedSet patterns = new TreeSet(new RegexSortingComparator()); // .... snip public RegexPatternSetFieldEditor(final String preferenceName, final String labelText, final Composite parent) { super(preferenceName, labelText, parent); } // .... snip protected void doFillIntoGrid(final Composite parent, final int numColumns) { // .... snip this.tbvPatternList = new TableViewer(table); this.tbvPatternList.setLabelProvider(new RegexPatternLabelProvider()); this.tbvPatternList.setContentProvider( new RegexPatternsContentProvider()); this.tbvPatternList.setInput(this.patterns); // .... snip } } </pre> <p> In this case the user just set <b><code>null</code></b> as input to the table viewer, <code>tbvPatternList</code>. Once you know that this method is called from the superclass constructor, it is self-evident why. Constructors are run before initializers and therefore at the time that the constructor is calling super, <code>this.patterns</code> is <code>null<code>. However, microseconds later when the call to the <code>doFillIntoGrid()</code> is done, the initializers are run. The result is that the viewer is looking at <code>null</code> and yet this.patterns is not null. </p> ---------------------------------------------------------------------------
bundles/org.eclipse.jface/src/org/eclipse/jface/preference/FieldEditor.java
* Set the GridData on button to be one that is spaced for the
     * current font.
     * @param button the button the data is being set on.
     */
    protected void setButtonLayoutData(Button button) {
        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        
        GC gc = new GC(button);
        gc.setFont(button.getFont());
        FontMetrics fontMetrics = gc.getFontMetrics();
        gc.dispose();
        int widthHint = org.eclipse.jface.dialogs.Dialog
                .convertVerticalDLUsToPixels(fontMetrics,
                        IDialogConstants.BUTTON_WIDTH);
        data.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT,
                SWT.DEFAULT, true).x);
        button.setLayoutData(data);
    }
    /**
     * Set whether or not the controls in the field editor
     * are enabled.
     * @param enabled The enabled state.
     * @param parent The parent of the controls in the group.
     *  Used to create the controls if required.
     */
    public void setEnabled(boolean enabled, Composite parent) {
        getLabelControl(parent).setEnabled(enabled);
    }
}