net.tourbook.common.font.FontFieldEditorExtended.java Source code

Java tutorial

Introduction

Here is the source code for net.tourbook.common.font.FontFieldEditorExtended.java

Source

/*******************************************************************************
 * Copyright (C) 2005, 2015 Wolfgang Schramm and Contributors
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation version 2 of the License.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
 *******************************************************************************/
package net.tourbook.common.font;

import net.tourbook.common.Messages;
import net.tourbook.common.UI;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.StringConverter;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseWheelListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FontDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Text;

/**
 * This is a copy of {@link orgFontFieldEditor} with an open & close listener which is fired when
 * the dialog is opened or closes. There are also other adjustments.
 * <p>
 * This can be used to keep parent dialog opened when the font dialog is opened.
 */
public class FontFieldEditorExtended extends FieldEditor {

    private final ListenerList _openListeners = new ListenerList();

    /**
     * The text for the change font button, or <code>null</code> if missing.
     */
    private String _buttonText;

    /**
     * The text for the preview, or <code>null</code> if no preview is desired
     */
    private String _previewAreaText;

    /*
     * UI controls
     */
    /**
     * The change font button, or <code>null</code> if none (before creation and after disposal).
     */
    private Button _btnChangeFont = null;

    /**
     * Font data for the chosen font button, or <code>null</code> if none.
     */
    private FontData[] chosenFont;

    /**
     * Editor lable.
     */
    private Label _lblEditor;

    /**
     * The label that displays the selected font, or <code>null</code> if none.
     */
    private Label _lblSelectedFont;

    /**
     * The previewer, or <code>null</code> if none.
     */
    private DefaultPreviewer _fontPreviewer;

    private Label _lblFontSize;

    private Composite _containerFontSize;
    private Spinner _spinFontSize;

    /**
     * Internal font previewer implementation.
     */
    private class DefaultPreviewer {

        private String _previewText;

        private Font _previewFont;
        private Text _txtPreviewText;

        /**
         * Constructor for the previewer.
         * 
         * @param previewText
         * @param parent
         */
        public DefaultPreviewer(final String previewText, final Composite parent) {

            _previewText = previewText;

            _txtPreviewText = new Text(parent, SWT.READ_ONLY | SWT.BORDER | SWT.WRAP);
            _txtPreviewText.addDisposeListener(new DisposeListener() {
                @Override
                public void widgetDisposed(final DisposeEvent e) {
                    if (_previewFont != null) {
                        _previewFont.dispose();
                    }
                }
            });

            if (_previewText != null) {
                _txtPreviewText.setText(_previewText);
            }
        }

        /**
         * @return the control the previewer is using
         */
        public Control getControl() {
            return _txtPreviewText;
        }

        public int getPreferredHeight() {
            return convertHorizontalDLUsToPixels(_txtPreviewText, 5 * 8);
        }

        /**
         * @return the preferred size of the previewer.
         */
        public int getPreferredWidth() {
            return convertHorizontalDLUsToPixels(_txtPreviewText, 40 * 4);
        }

        public void setEnabled(final boolean isEnabled) {
            _txtPreviewText.setEnabled(isEnabled);
        }

        /**
         * Set the font to display with
         * 
         * @param fontData
         */
        public void setFont(final FontData[] fontData) {

            if (_previewFont != null) {
                _previewFont.dispose();
            }

            _previewFont = new Font(_txtPreviewText.getDisplay(), fontData);
            _txtPreviewText.setFont(_previewFont);
        }
    }

    /**
     * Creates a new font field editor
     */
    protected FontFieldEditorExtended() {
    }

    /**
     * Creates a font field editor without a preview.
     * 
     * @param name
     *            the name of the preference this field editor works on
     * @param labelText
     *            the label text of the field editor
     * @param parent
     *            the parent of the field editor's control
     */
    public FontFieldEditorExtended(final String name, final String labelText, final Composite parent) {
        this(name, labelText, null, parent);

    }

    /**
     * Creates a font field editor with an optional preview area.
     * 
     * @param name
     *            the name of the preference this field editor works on
     * @param labelText
     *            the label text of the field editor
     * @param previewAreaText
     *            the text used for the preview window. If it is <code>null</code> there will be no
     *            preview area,
     * @param parent
     *            the parent of the field editor's control
     */
    public FontFieldEditorExtended(final String name, final String labelText, final String previewAreaText,
            final Composite parent) {
        init(name, labelText);

        _previewAreaText = previewAreaText;
        _buttonText = JFaceResources.getString("openChange"); //$NON-NLS-1$

        createControl(parent);
    }

    public void addOpenListener(final IFontDialogListener listener) {
        _openListeners.add(listener);
    }

    @Override
    protected void adjustForNumColumns(final int numColumns) {

        GridData data = new GridData();
        if (_lblSelectedFont.getLayoutData() != null) {
            data = (GridData) _lblSelectedFont.getLayoutData();
        }

        data.horizontalSpan = numColumns - getNumberOfControls() + 1;
        _lblSelectedFont.setLayoutData(data);
    }

    @Override
    protected void applyFont() {

        if (chosenFont != null && _fontPreviewer != null) {
            _fontPreviewer.setFont(chosenFont);
        }
    }

    @Override
    protected void doFillIntoGrid(final Composite parent, final int numColumns) {

        //      parent.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW));
        {
            /*
             * Label: Font editor
             */
            // create editor label
            _lblEditor = getLabelControl(parent);

            final GridData gd = new GridData();
            gd.verticalAlignment = SWT.BEGINNING;

            _lblEditor.setLayoutData(gd);
        }

        {
            /*
             * Label: Selected font
             */
            _lblSelectedFont = getValueControl(parent);

            final GridData gd = new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL);
            gd.horizontalSpan = numColumns - getNumberOfControls() + 1;
            _lblSelectedFont.setLayoutData(gd);
        }

        final Composite container = new Composite(parent, SWT.NONE);
        GridDataFactory.fillDefaults().grab(true, false).applyTo(container);
        GridLayoutFactory.fillDefaults().numColumns(2).applyTo(container);
        //      container.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_MAGENTA));
        {
            {
                /*
                 * Button: Change font
                 */
                _btnChangeFont = getChangeControl(container);

                final int widthHint = convertHorizontalDLUsToPixels(_btnChangeFont, IDialogConstants.BUTTON_WIDTH);
                final int defaultWidth = _btnChangeFont.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x;

                final GridData gd = new GridData();
                gd.widthHint = Math.max(widthHint, defaultWidth);
                gd.verticalAlignment = SWT.BEGINNING;
                gd.horizontalSpan = 2;
                _btnChangeFont.setLayoutData(gd);
            }
            {
                /*
                 * Font size
                 */
                _containerFontSize = new Composite(container, SWT.NONE);
                GridDataFactory.fillDefaults().grab(true, false).applyTo(_containerFontSize);
                GridLayoutFactory.fillDefaults().numColumns(2).applyTo(_containerFontSize);
                //            _containerFontSize.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_GREEN));
                {
                    // Label
                    _lblFontSize = new Label(_containerFontSize, SWT.NONE);
                    GridDataFactory.fillDefaults()//
                            .align(SWT.FILL, SWT.CENTER).applyTo(_lblFontSize);
                    _lblFontSize.setText(Messages.Font_Editor_Label_FontSize);

                    // Spinner
                    _spinFontSize = new Spinner(_containerFontSize, SWT.BORDER);
                    _spinFontSize.setMinimum(2);
                    _spinFontSize.setMaximum(100);
                    _spinFontSize.setPageIncrement(5);
                    _spinFontSize.addSelectionListener(new SelectionAdapter() {
                        @Override
                        public void widgetSelected(final SelectionEvent e) {
                            onChangeFontSize();
                        }
                    });
                    _spinFontSize.addMouseWheelListener(new MouseWheelListener() {

                        @Override
                        public void mouseScrolled(final MouseEvent event) {
                            UI.adjustSpinnerValueOnMouseScroll(event);
                            onChangeFontSize();
                        }
                    });
                }
            }
        }
        {
            /*
             * Font preview
             */
            if (_previewAreaText != null) {

                _fontPreviewer = new DefaultPreviewer(_previewAreaText, parent);

                final GridData gd = new GridData(GridData.FILL_HORIZONTAL);
                gd.widthHint = _fontPreviewer.getPreferredWidth();
                gd.heightHint = _fontPreviewer.getPreferredHeight();
                gd.verticalSpan = 2;
                _fontPreviewer.getControl().setLayoutData(gd);
            }
        }
    }

    @Override
    protected void doLoad() {

        if (_btnChangeFont == null) {
            return;
        }

        updateFont(PreferenceConverter.getFontDataArray(getPreferenceStore(), getPreferenceName()));
    }

    @Override
    protected void doLoadDefault() {

        if (_btnChangeFont == null) {
            return;
        }

        updateFont(PreferenceConverter.getDefaultFontDataArray(getPreferenceStore(), getPreferenceName()));
    }

    @Override
    protected void doStore() {

        if (chosenFont != null) {
            PreferenceConverter.setValue(getPreferenceStore(), getPreferenceName(), chosenFont);
        }
    }

    private void fireFontChanged(final FontData font) {

        FontData[] oldFont = chosenFont;
        if (oldFont == null) {
            oldFont = JFaceResources.getDefaultFont().getFontData();
        }
        setPresentsDefaultValue(false);

        final FontData[] newFontData = new FontData[1];
        newFontData[0] = font;
        updateFont(newFontData);

        fireValueChanged(VALUE, oldFont[0], font);
    }

    /**
     * Fire an open event that the dialog is opened or closes.
     */
    private void fireOpenEvent(final boolean isOpened) {

        final Object[] listeners = _openListeners.getListeners();

        for (final Object listener : listeners) {

            final IFontDialogListener dialogListener = (IFontDialogListener) listener;

            SafeRunnable.run(new SafeRunnable() {
                @Override
                public void run() {
                    dialogListener.fontDialogOpened(isOpened);
                }
            });
        }
    }

    /**
     * Returns the change button for this field editor.
     * 
     * @param parent
     *            The Composite to create the button in if required.
     * @return the change button
     */
    protected Button getChangeControl(final Composite parent) {

        if (_btnChangeFont == null) {

            _btnChangeFont = new Button(parent, SWT.PUSH);
            if (_buttonText != null) {
                _btnChangeFont.setText(_buttonText);
            }

            _btnChangeFont.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(final SelectionEvent event) {

                    final FontDialog fontDialog = new FontDialog(_btnChangeFont.getShell());

                    if (chosenFont != null) {
                        fontDialog.setFontList(chosenFont);
                    }

                    fontDialog.setEffectsVisible(false);

                    fireOpenEvent(true);

                    final FontData font = fontDialog.open();

                    fireOpenEvent(false);

                    if (font != null) {
                        fireFontChanged(font);
                    }

                }
            });
            _btnChangeFont.addDisposeListener(new DisposeListener() {
                @Override
                public void widgetDisposed(final DisposeEvent event) {
                    _btnChangeFont = null;
                }
            });
            _btnChangeFont.setFont(parent.getFont());
            setButtonLayoutData(_btnChangeFont);
        } else {
            // parent check will fail because of the rearranged controls, e.g. font size
            //         checkParent(_btnChangeFont, parent);
        }
        return _btnChangeFont;
    }

    /**
     * Get the system default font data.
     * 
     * @return FontData[]
     */
    private FontData[] getDefaultFontData() {
        return _lblSelectedFont.getDisplay().getSystemFont().getFontData();
    }

    @Override
    public int getNumberOfControls() {

        //      if (_fontPreviewer == null) {
        //         return 3;
        //      }
        //
        //      return 4;

        return 2;
    }

    /**
     * Returns the preferred preview height.
     * 
     * @return the height, or <code>-1</code> if no previewer is installed
     */
    public int getPreferredPreviewHeight() {

        if (_fontPreviewer == null) {
            return -1;
        }

        return _fontPreviewer.getPreferredHeight();
    }

    /**
     * Returns the preview control for this field editor.
     * 
     * @return the preview control
     */
    public Control getPreviewControl() {
        if (_fontPreviewer == null) {
            return null;
        }

        return _fontPreviewer.getControl();
    }

    /**
     * Returns the value control for this field editor. The value control displays the currently
     * selected font name.
     * 
     * @param parent
     *            The Composite to create the viewer in if required
     * @return the value control
     */
    protected Label getValueControl(final Composite parent) {

        if (_lblSelectedFont == null) {
            _lblSelectedFont = new Label(parent, SWT.LEFT);
            _lblSelectedFont.setFont(parent.getFont());
            _lblSelectedFont.addDisposeListener(new DisposeListener() {
                @Override
                public void widgetDisposed(final DisposeEvent event) {
                    _lblSelectedFont = null;
                }
            });
        } else {
            checkParent(_lblSelectedFont, parent);
        }

        return _lblSelectedFont;
    }

    private void onChangeFontSize() {

        final FontData[] selectedFont = chosenFont;

        final FontData font = selectedFont[0];
        font.setHeight(_spinFontSize.getSelection());

        final FontData[] validFont = JFaceResources.getFontRegistry().filterData(selectedFont,
                _lblSelectedFont.getDisplay());

        fireFontChanged(validFont[0]);
    }

    public void removeOpenListener(final IFontDialogListener listener) {
        _openListeners.remove(listener);
    }

    /**
     * Sets the text of the change button.
     * 
     * @param text
     *            the new text
     */
    public void setChangeButtonText(final String text) {

        Assert.isNotNull(text);

        _buttonText = text;
        if (_btnChangeFont != null) {
            _btnChangeFont.setText(text);
        }
    }

    @Override
    public void setEnabled(final boolean isEnabled, final Composite parent) {

        super.setEnabled(isEnabled, parent);

        getChangeControl(parent).setEnabled(isEnabled);
        getValueControl(parent).setEnabled(isEnabled);

        if (_fontPreviewer != null) {
            _fontPreviewer.setEnabled(isEnabled);
        }

        _lblFontSize.setEnabled(isEnabled);
        _spinFontSize.setEnabled(isEnabled);
    }

    /**
     * Set indent for the first column fields.
     * 
     * @param horizontalIndent
     * @param verticalIndent
     */
    public void setFirstColumnIndent(final int horizontalIndent, final int verticalIndent) {

        GridData gd = (GridData) _lblEditor.getLayoutData();
        gd.horizontalIndent = horizontalIndent;
        gd.verticalIndent = verticalIndent;

        gd = (GridData) _btnChangeFont.getLayoutData();
        gd.horizontalIndent = horizontalIndent;
        gd.verticalIndent = verticalIndent;

        gd = (GridData) _containerFontSize.getLayoutData();
        gd.horizontalIndent = horizontalIndent;
        gd.verticalIndent = verticalIndent;
    }

    /**
     * Store the default preference for the field being edited
     */
    protected void setToDefault() {

        final FontData[] defaultFontData = PreferenceConverter.getDefaultFontDataArray(getPreferenceStore(),
                getPreferenceName());

        PreferenceConverter.setValue(getPreferenceStore(), getPreferenceName(), defaultFontData);
    }

    /**
     * Updates the change font button and the previewer to reflect the newly selected font.
     * 
     * @param font
     *            The FontData[] to update with.
     */
    private void updateFont(final FontData font[]) {

        FontData[] bestFont = JFaceResources.getFontRegistry().filterData(font, _lblSelectedFont.getDisplay());

        //if we have nothing valid do as best we can
        if (bestFont == null) {
            bestFont = getDefaultFontData();
        }

        //Now cache this value in the receiver
        this.chosenFont = bestFont;

        if (_lblSelectedFont != null) {
            _lblSelectedFont.setText(StringConverter.asString(chosenFont[0]));
        }
        if (_fontPreviewer != null) {
            _fontPreviewer.setFont(bestFont);
        }

        // update font size widget
        final int fontHeight = bestFont[0].getHeight();
        _spinFontSize.setSelection(fontHeight);
    }

}