uk.ac.gda.dls.client.views.ReadonlyScannableComposite.java Source code

Java tutorial

Introduction

Here is the source code for uk.ac.gda.dls.client.views.ReadonlyScannableComposite.java

Source

/*-
 * Copyright  2013 Diamond Light Source Ltd.
 *
 * This file is part of GDA.
 *
 * GDA is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License version 3 as published by the Free
 * Software Foundation.
 *
 * GDA 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 GDA. If not, see <http://www.gnu.org/licenses/>.
 */

package uk.ac.gda.dls.client.views;

import java.text.NumberFormat;
import java.util.Map;
import java.util.Scanner;

import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import gda.device.DeviceException;
import gda.device.Scannable;
import gda.device.scannable.ScannableGetPositionWrapper;
import gda.device.scannable.ScannablePositionChangeEvent;
import gda.device.scannable.ScannableStatus;
import gda.observable.IObserver;
import uk.ac.gda.common.rcp.util.EclipseWidgetUtils;

public class ReadonlyScannableComposite extends Composite {
    private static final Logger logger = LoggerFactory.getLogger(ReadonlyScannableComposite.class);
    private Text text;
    private Scannable scannable;
    private IObserver observer;
    private String val = "...";
    private Display display;
    private Runnable setTextRunnable;
    private String[] formats;
    private String suffix = "";
    private Integer decimalPlaces;
    private Integer minPeriodMS = null;
    private Boolean textUpdateScheduled = false;
    private Map<String, Integer> colourMap;

    public Map<String, Integer> getColourMap() {
        return colourMap;
    }

    /**
     * 
     * @param colourMap map of ids to pass to Display.getSystemColor to allow setting of foreground based on value
     * Useful for enums
     */
    public void setColourMap(Map<String, Integer> colourMap) {
        this.colourMap = colourMap;
    }

    public Integer getMinPeriodMS() {
        return minPeriodMS;
    }

    public void setMinPeriodMS(Integer minPeriodMS) {
        this.minPeriodMS = minPeriodMS;
    }

    public ReadonlyScannableComposite(Composite parent, int style, final Scannable scannable, String label,
            final String units, Integer decimalPlaces) {
        super(parent, style);
        this.display = parent.getDisplay();
        this.scannable = scannable;
        this.decimalPlaces = decimalPlaces;

        if (StringUtils.hasLength(units)) {
            suffix = " " + units;
        }

        formats = scannable.getOutputFormat();
        GridLayoutFactory.fillDefaults().numColumns(2).applyTo(this);
        GridDataFactory.fillDefaults().applyTo(this);

        Label lbl = new Label(this, SWT.NONE | SWT.CENTER);
        lbl.setText(StringUtils.hasLength(label) ? label : scannable.getName());

        int textStyle = SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY | SWT.CENTER;
        text = new Text(this, textStyle);
        text.setEditable(false);
        setTextRunnable = new Runnable() {

            @Override
            public void run() {
                beforeUpdateText(text, val);
                int currentLength = text.getText().length();
                String valPlusUnits = val + suffix;
                text.setText(valPlusUnits);
                int diff = valPlusUnits.length() - currentLength;
                if (diff > 0 || diff < -3)
                    EclipseWidgetUtils.forceLayoutOfTopParent(ReadonlyScannableComposite.this);
                if (colourMap != null) {
                    Integer colorId = colourMap.get(val);
                    if (colorId != null) {
                        text.setForeground(Display.getCurrent().getSystemColor(colorId));
                    }
                }
                textUpdateScheduled = false;
                afterUpdateText(text, val);
            }
        };

        observer = new IObserver() {

            @Override
            public void update(Object source, Object arg) {
                if (arg instanceof ScannablePositionChangeEvent) {
                    final ScannablePositionChangeEvent event = (ScannablePositionChangeEvent) arg;
                    setVal(new ScannableGetPositionWrapper(event.newPosition, formats)
                            .getStringFormattedValues()[0]);
                } else if (arg instanceof ScannableStatus
                        && ((ScannableStatus) arg).status == ScannableStatus.IDLE) {
                    try {
                        ScannableGetPositionWrapper wrapper = new ScannableGetPositionWrapper(
                                scannable.getPosition(), formats);
                        val = wrapper.getStringFormattedValues()[0];
                    } catch (DeviceException e1) {
                        val = "Error";
                        logger.error("Error getting position for " + scannable.getName(), e1);
                    }
                    setVal(val);
                } else if (arg instanceof String) {
                    setVal((String) arg);
                } else {
                    ScannableGetPositionWrapper wrapper = new ScannableGetPositionWrapper(arg, formats);
                    setVal(wrapper.getStringFormattedValues()[0]);
                }
            }
        };

        try {
            ScannableGetPositionWrapper wrapper = new ScannableGetPositionWrapper(scannable.getPosition(), formats);
            val = wrapper.getStringFormattedValues()[0];
        } catch (DeviceException e1) {
            val = "Error";
            logger.error("Error getting position for " + scannable.getName(), e1);
        }
        setVal(val);

        scannable.addIObserver(observer);
    }

    private void setVal(String newVal) {
        if (decimalPlaces != null) {
            Scanner sc = new Scanner(newVal.trim());
            if (sc.hasNextDouble()) {
                NumberFormat format = NumberFormat.getInstance();
                format.setMaximumFractionDigits(decimalPlaces.intValue());
                newVal = format.format(sc.nextDouble());
            }
            sc.close();
        }
        val = newVal;
        if (!isDisposed()) {
            if (minPeriodMS != null) {
                if (!textUpdateScheduled) {
                    textUpdateScheduled = true;
                    display.asyncExec(new Runnable() {

                        @Override
                        public void run() {
                            display.timerExec(minPeriodMS, setTextRunnable);
                        }
                    });
                }
            } else {
                display.asyncExec(setTextRunnable);
            }
        }
    }

    @Override
    public void dispose() {
        scannable.deleteIObserver(observer);
        super.dispose();
    }

    @SuppressWarnings("unused")
    protected void beforeUpdateText(Text text, String value) {
    }

    @SuppressWarnings("unused")
    protected void afterUpdateText(Text text, String value) {
    }

}