package org.csstudio.sds.components.ui.internal.figures; import java.util.ArrayList; import org.csstudio.sds.ui.figures.BorderAdapter; import org.csstudio.sds.ui.figures.CrossedOutAdapter; import org.csstudio.sds.ui.figures.IBorderEquippedWidget; import org.csstudio.sds.ui.figures.ICrossedFigure; import org.csstudio.sds.ui.figures.IRhombusEquippedWidget; import org.csstudio.sds.ui.figures.RhombusAdapter; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.draw2d.ActionEvent; import org.eclipse.draw2d.ActionListener; import org.eclipse.draw2d.ArrowButton; import org.eclipse.draw2d.BorderLayout; import org.eclipse.draw2d.Figure; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.GridData; import org.eclipse.draw2d.GridLayout; import org.eclipse.draw2d.Label; import org.eclipse.draw2d.LineBorder; import org.eclipse.draw2d.RectangleFigure; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; /** * The view for ThumbWheel. * * @author avrecko * */ public class RefreshableThumbWheelFigure extends RectangleFigure implements IAdaptable { /** * A border adapter, which covers all border handlings. */ private IBorderEquippedWidget _borderAdapter; // need reference because of changing font and color private CharBox dot; private CharBox minus; private GridLayout layout = new GridLayout(); // before the dot. 123,45 - we store 123 private DigitBox[] wholePart; // part after the dot. 123,45 - we store 45 private DigitBox[] decimalPart; private int wholePartDigits; private int decimalPartDigits; private boolean test; private int internalBorderWidth; private final ArrayList<WheelListener> listeners = new ArrayList<WheelListener>(); private Font wheelFont; private CrossedOutAdapter _crossedOutAdapter; private RhombusAdapter _rhombusAdapter; public RefreshableThumbWheelFigure(final int integerWheels, final int decimalDigits) { wholePartDigits = integerWheels; decimalPartDigits = decimalDigits; // we will be displaying the widget anyway so I don't see a point in // deferring this till later. createWidgets(); } @Override public void paint(final Graphics graphics) { super.paint(graphics); _crossedOutAdapter.paint(graphics); _rhombusAdapter.paint(graphics); } public boolean isTest() { return test; } public void setTest(final boolean test) { this.test = test; } /** * Creates new widgets if needed to satisfy number of wheels specified. */ private void createWidgets() { removeAll(); wholePart = null; decimalPart = null; layout = new GridLayout(2 + wholePartDigits + decimalPartDigits, false); layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; setLayoutManager(layout); minus = new CharBox(' '); add(minus); setConstraint(minus, createGridData()); wholePart = new DigitBox[wholePartDigits]; for (int i = 0; i < wholePartDigits; i++) { DigitBox box = new DigitBox(i, false); add(box); wholePart[wholePartDigits - i - 1] = box; setConstraint(box, createGridData()); } dot = new CharBox('.'); add(dot); setConstraint(dot, createGridData()); decimalPart = new DigitBox[decimalPartDigits]; for (int i = 0; i < decimalPartDigits; i++) { DigitBox box = new DigitBox(i, true); add(box); decimalPart[i] = box; setConstraint(box, createGridData()); } setInternalBorderThickness(internalBorderWidth); setWheelFonts(wheelFont); revalidate(); } public GridData createGridData() { GridData data = new GridData(); data.horizontalAlignment = GridData.FILL; data.verticalAlignment = GridData.FILL; data.grabExcessVerticalSpace = true; data.grabExcessHorizontalSpace = true; return data; } /** * {@inheritDoc} */ @Override public Object getAdapter(final Class adapter) { if (adapter == IBorderEquippedWidget.class) { if (_borderAdapter == null) { _borderAdapter = new BorderAdapter(this); } return _borderAdapter; } else if (adapter == ICrossedFigure.class) { if (_crossedOutAdapter == null) { _crossedOutAdapter = new CrossedOutAdapter(this); } return _crossedOutAdapter; } else if (adapter == IRhombusEquippedWidget.class) { if (_rhombusAdapter == null) { _rhombusAdapter = new RhombusAdapter(this); } return _rhombusAdapter; } return null; } public void setInternalBorderThickness(final int thickness) { this.internalBorderWidth = thickness; for (DigitBox box : wholePart) { box.setBorderThickness(thickness); } for (DigitBox box : decimalPart) { box.setBorderThickness(thickness); } dot.setBorderThickness(thickness); minus.setBorderThickness(thickness); } public void setInternalBorderColor(final Color color) { if(color == null){ return; } for (DigitBox box : wholePart) { box.setBorderColor(color); } for (DigitBox box : decimalPart) { box.setBorderColor(color); } dot.setBorderColor(color); minus.setBorderColor(color); } /** * Represents a box with a single char in it. * */ private static class CharBox extends Figure { private final Label label; private Color color; private int thickness; public CharBox(final char ch) { BorderLayout layout = new BorderLayout(); layout.setVerticalSpacing(0); setLayoutManager(layout); label = new Label("" + ch); add(label); setConstraint(label, BorderLayout.CENTER); } public void setChar(final char c) { label.setText("" + c); } public void setLabelFont(final Font font) { label.setFont(font); } public void setBorderThickness(final int thickness) { this.thickness = thickness; if (thickness == 0) { setBorder(null); } else { if (color != null) { setBorder(new LineBorder(color, thickness)); } else { setBorder(new LineBorder(thickness)); } } } public void setBorderColor(final Color color) { this.color = color; if (color == null) { setBorder(null); } else { setBorder(new LineBorder(color, thickness)); } } @SuppressWarnings("unused") public void setLabelFontColor(final Color font) { label.setForegroundColor(color); } } /** * Represents a box with a digit and up and down button. Calls * increment/decrement listeners on button clicks. * */ private class DigitBox extends Figure { private final Label label; private int thickness; private Color color; public DigitBox(final int positionIndex, final boolean isDecimal) { BorderLayout layout = new BorderLayout(); layout.setVerticalSpacing(0); setLayoutManager(layout); label = new Label("0"); ArrowButton up = new ArrowButton(ArrowButton.NORTH); up.setPreferredSize(20, 20); if (isDecimal) { up.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent event) { fireIncrementDecimalListeners(positionIndex); } }); } else { up.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent event) { fireIncrementIntegerListeners(wholePartDigits - positionIndex - 1); } }); } add(up); setConstraint(up, BorderLayout.TOP); label.setPreferredSize(20, 10); add(label); setConstraint(label, BorderLayout.CENTER); ArrowButton down = new ArrowButton(ArrowButton.SOUTH); down.setPreferredSize(20, 20); if (isDecimal) { down.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent event) { fireDecrementDecimalListeners(positionIndex); } }); } else { down.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent event) { fireDecrementIntegerListeners(wholePartDigits - positionIndex - 1); } }); } add(down, BorderLayout.BOTTOM); } public void setLabelFont(final Font font) { label.setFont(font); } public void setBorderThickness(final int thickness) { this.thickness = thickness; if (thickness == 0) { setBorder(null); } else { if (color != null) { setBorder(new LineBorder(color, thickness)); } else { setBorder(new LineBorder(thickness)); } } } public void setBorderColor(final Color color) { this.color = color; if (color == null) { setBorder(null); } else { setBorder(new LineBorder(color, thickness)); } } public void setValue(final String value) { label.setText("" + value); } @SuppressWarnings("unused") public void setLabelFontColor(final Color color) { label.setForegroundColor(color); } } public void setWholeDigitsPart(final int wholePartDigits2) { wholePartDigits = wholePartDigits2; createWidgets(); } public void setDecimalDigitsPart(final int decimalPartDigits2) { decimalPartDigits = decimalPartDigits2; createWidgets(); } public void setIntegerWheel(final int index, final char value) { DigitBox box = wholePart[index]; box.setValue("" + value); } public void setDecimalWheel(final int index, final char value) { DigitBox box = decimalPart[index]; box.setValue("" + value); } public void showMinus(final boolean b) { if (b) { minus.setChar('-'); } else { minus.setChar(' '); } } // LISTENER PART public void addWheelListener(final WheelListener listener) { listeners.add(listener); } public void removeWheelListener(final WheelListener listener) { listeners.remove(listener); } private void fireDecrementIntegerListeners(final int index) { for (WheelListener listener : listeners) { listener.decrementIntegerPart(index); } } private void fireIncrementIntegerListeners(final int index) { for (WheelListener listener : listeners) { listener.incrementIntegerPart(index); } } private void fireIncrementDecimalListeners(final int index) { for (WheelListener listener : listeners) { listener.incrementDecimalPart(index); } } private void fireDecrementDecimalListeners(final int index) { for (WheelListener listener : listeners) { listener.decrementDecimalPart(index); } } public static interface WheelListener { /** * Signals increment on a wheel of the integer part. * * @param index */ void incrementIntegerPart(int index); /** * Signals increment on a wheel of the decimal part. * * @param index */ void incrementDecimalPart(int index); /** * Signals decrement on a wheel of the integer part. * * @param index */ void decrementIntegerPart(int index); /** * Signals decrement on a wheel of the integer part. * * @param index */ void decrementDecimalPart(int index); } public void setWheelFonts(final Font font) { this.wheelFont = font; for (DigitBox box : wholePart) { box.setLabelFont(font); } for (DigitBox box : decimalPart) { box.setLabelFont(font); } dot.setLabelFont(font); minus.setLabelFont(font); } }