wrps-demo-kit/99-reference/ciserver-hmi-deployment/components/ExtendedJSlider.java
Clio Liu 4fc5f80b21 chore: preserve reference files byte-for-byte
.gitattributes normalised the CI Server exports under 99-reference/ to LF.
They are a format specification and must match what CI Server actually
wrote, so mark the folder -text and restore the originals.
2026-09-02 15:17:49 +10:00

533 lines
16 KiB
Java

/*-
* @(#)ExtendedJSlider.java
*
* Copyright: Yokogawa, All rights reserved.
* YOKOGAWA PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* Author: C. Horevoorts
*
* ----------------------------------------------------------------------------
* Changes ....
* ----------------------------------------------------------------------------
* Who When Change What
* ----------------------------------------------------------------------------
* HVS Jan-05 e9435 First version documented
* HVS Feb-09 i10167 Make slider more accurate
* BNL Feb-09 i10167 Make slider even more accurate
* BNL Feb-09 e10104 Correct update tick spacing on min and max change
* HVS Feb-12 e10575 For runtime shore settings until validate() is called
* HVS Jun-20 e12272 Port to JViews 2017.2
*
*/
package fasttools.jwui.ilv.graphic;
import fasttools.jtools.common.Format;
import fasttools.jtools.common.FtException;
import fasttools.jtools.common.Utils;
import fasttools.jwui.ilv.swing.INonRectangularJComponent;
import fasttools.jwui.ilv.swing.IJComponentTagger;
import fasttools.jwui.JwuiConfiguration;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.beans.PropertyChangeListener;
import java.text.DecimalFormat;
import java.util.Dictionary;
import java.util.Hashtable;
/**
* This class extends the swing JSlider to be used in the ExtendedJComponent container.
* The ExtendedJComponent container extends IlvGraphic to swing components
* can be used in views.
*/
public class ExtendedJSlider extends JSlider implements IJComponentTagger, ChangeListener, IAction, INonRectangularJComponent {
private double cMaximum;
private double cMinimum;
private double cMajorTickSpacing;
private double cMinorTickSpacing;
private String cFormat = "";
private static double PHYS_HIGH = Integer.MAX_VALUE / 2;
private String cLabel = "";
private int cOldValue;
private double cOldDoubleValue;
private boolean cInitializing;
private boolean cTrackDrag;
private boolean cValidated;
/**
* Constructor.
*/
public ExtendedJSlider() {
try {
cInitializing = true;
if (JwuiConfiguration.isEditor()) {
cValidated = true;
}
setMaximumAsDouble(100.0);
setMajorTickSpacingAsDouble(10.);
setMaximum((int) PHYS_HIGH);
setOpaque(false);
} finally {
cInitializing = false;
}
}
/**
* If becomes visable then correct min/max/tick and redraw labels
*/
public void validate() {
if (!cValidated) {
cValidated = true;
if (cMinimum >= cMaximum) {
cMinimum = cMaximum - (cMaximum - cMinimum);
}
setMinorTickSpacingAsDouble(cMinorTickSpacing);
setMajorTickSpacingAsDouble(cMajorTickSpacing);
setValueAsDouble(cOldDoubleValue);
}
}
/**
* Sets the maximum range of the slider.
*
* @param maximum The maximum range
*/
public void setMaximumAsDouble(double maximum) {
if (cValidated) {
if (cMaximum != maximum) {
if (cMinimum >= maximum) {
cMinimum = maximum - (cMaximum - cMinimum);
}
cMaximum = maximum;
reCreateLabels();
}
} else
cMaximum = maximum;
}
/**
* Returns the maximum range.
*
* @return The maximum range
*/
public double getMaximumAsDouble() {
return cMaximum;
}
/**
* Sets the minimum range.
*
* @param minimum The minimum range
*/
public void setMinimumAsDouble(double minimum) {
if (cValidated) {
if (cMinimum != minimum) {
if (cMaximum <= minimum) {
cMaximum = minimum + (cMaximum - cMinimum);
}
cMinimum = minimum;
reCreateLabels();
}
}
else
cMinimum = minimum;
}
/**
* Returns the minimum range.
*
* @return The minimum range
*/
public double getMinimumAsDouble() {
return cMinimum;
}
/**
* Sets the slider position.
*
* @param value The slider position
*/
public void setValueAsDouble(double value) {
cOldDoubleValue = value;
if (cValidated) {
int mValue = (int) Math.floor((value - cMinimum) / (cMaximum - cMinimum) * PHYS_HIGH);
cOldValue = mValue;
setValue(mValue);
}
}
/**
* Returns the slider position.
*
* @return The slider psoition
*/
public double getValueAsDouble() {
return cnvToDouble(getValue());
}
/**
* Sets the major tick spacing.
*
* @param spacing The major tick spacing
*/
public void setMajorTickSpacingAsDouble(double spacing) {
cMajorTickSpacing = spacing;
if (cValidated) {
setMajorTickSpacing((int) Math.floor(spacing / (cMaximum - cMinimum) * PHYS_HIGH));
reCreateLabels();
}
}
/**
* Returns the major tick spacing.
*
* @return The major tick spacing
*/
public double getMajorTickSpacingAsDouble() {
return cMajorTickSpacing;
}
/**
* Sets the major tick spacing.
*
* @param spacing The major tick spacing
*/
public void setMinorTickSpacingAsDouble(double spacing) {
if (cValidated) {
setMinorTickSpacing((int) Math.floor(spacing / (cMaximum - cMinimum) * PHYS_HIGH));
}
cMinorTickSpacing = spacing;
}
/**
* Returns the minor tick spacing.
*
* @return The minor tick spacing
*/
public double getMinorTickSpacingAsDouble() {
return cMinorTickSpacing;
}
/**
* Sets the slider orientation.
*
* @param vertical True for vertical, false for horizontal
*/
public void setVertical(boolean vertical) {
setOrientation(vertical ? JSlider.VERTICAL : JSlider.HORIZONTAL);
}
/**
* Returns the slider orientation.
*
* @return True for vertical, false for horizontal
*/
public boolean isVertical() {
return getOrientation() == JSlider.VERTICAL;
}
/**
* Overriiden to create labels
*
* @param paintLabels True if painting labels
*/
public void setPaintLabels(boolean paintLabels) {
super.setPaintLabels(paintLabels);
reCreateLabels();
}
/**
* If true then the value changes while dragging the slider, else
* the value is set when the mouse is released.
*
* @param track True to track drags
*/
public void setTrackDrag(boolean track) {
cTrackDrag = track;
}
/**
* Returns the track drag.
*
* @return True to track drags
*/
public boolean isTrackDrag() {
return cTrackDrag;
}
/**
* Internally called to recreate the slider labels.
*/
private void reCreateLabels() {
if (getPaintLabels()) {
DecimalFormat mFormat;
Dictionary<Integer, JLabel> mLabelTable = new Hashtable<Integer, JLabel>(20);
String[] mLabels;
if (cLabel != null && cLabel.length() > 0) {
mLabels = Utils.split(cLabel, ';');
} else {
mLabels = new String[0];
}
double mIncrement = cMajorTickSpacing;
if (mIncrement <= 0) {
mIncrement = cMaximum - cMinimum;
} else if ((cMaximum - cMinimum) / mIncrement > 200.) {
mIncrement = cMaximum - cMinimum;
}
int mIndex = 0;
for (double mLabelMajorTick = cMinimum; mLabelMajorTick <= cMaximum; mLabelMajorTick += mIncrement, mIndex++) {
JLabel mLabel;
String mLabelText;
if (mLabels.length > mIndex) {
mLabelText = mLabels[mIndex];
} else {
try {
mLabelText = Format.format(mLabelMajorTick, cFormat);
} catch (FtException e) {
mLabelText = "" + mLabelMajorTick;
}
}
mLabel = new JLabel(mLabelText, JLabel.CENTER);
mLabel.setFont(getFont());
mLabel.setForeground(getForeground());
mLabelTable.put((int) Math.floor((mLabelMajorTick - cMinimum) / (cMaximum - cMinimum) * PHYS_HIGH), mLabel);
}
setLabelTable(mLabelTable);
}
setMajorTickSpacing((int) Math.floor(cMajorTickSpacing / (cMaximum - cMinimum) * PHYS_HIGH));
setMinorTickSpacing((int) Math.floor(cMinorTickSpacing / (cMaximum - cMinimum) * PHYS_HIGH));
}
/**
* Sets the font.
*
* @param font The font
*/
public void setFont(Font font) {
super.setFont(font);
reCreateLabels();
}
/**
* Sets the foreground color.
*
* @param color The foreground color
*/
public void setForeground(Color color) {
super.setForeground(color);
reCreateLabels();
}
/**
* Sets the format for the labels.
*
* @param format The format string
*/
public void setFormat(String format) {
if (format == null) {
format = "";
}
if (!cFormat.equals(format)) {
String mOldFormat = cFormat;
try {
cFormat = format;
reCreateLabels();
} catch (Exception e) {
cFormat = mOldFormat;
reCreateLabels();
}
}
}
/**
* Returns the format of the labels.
*
* @return The format string
*/
public String getFormat() {
return cFormat;
}
/**
* Sets the label.
*
* @param label The label
*/
public void setLabel(String label) {
String mOldLabel = cLabel;
try {
cLabel = label;
reCreateLabels();
} catch (Exception e) {
cLabel = mOldLabel;
reCreateLabels();
}
}
/**
* Returns the label.
*
* @return The label
*/
public String getLabel() {
return cLabel;
}
/**
* Add a property listener.
*
* @param listener The property listener
*/
public void addPropertyChangeListener(PropertyChangeListener listener) {
removeChangeListener(this);
addChangeListener(this);
super.addPropertyChangeListener(listener);
}
/**
* Invoked when the target of the listener has changed its state.
*
* @param e a ChangeEvent object
*/
public void stateChanged(ChangeEvent e) {
if (!getModel().getValueIsAdjusting() || cTrackDrag) {
int mValue = getValue();
if (mValue != cOldValue && !cInitializing) {
int mOldValue = cOldValue;
cOldValue = mValue;
firePropertyChange("ValueAsDouble", cnvToDouble(mOldValue), cnvToDouble(mValue));
fireActionEvent();
}
cOldValue = mValue;
}
}
/**
* Converts the physical slider value to the double value.
* If snapping is enabled, the value is also snapped to the nearest tick.
*
* @param value The physical slider value
* @return The double value
*/
private double cnvToDouble(int value) {
double mValue = value * (cMaximum - cMinimum) / PHYS_HIGH + cMinimum;
if (getSnapToTicks()) {
int mMajorTickSpacing = getMajorTickSpacing();
int mMinorTickSpacing = getMinorTickSpacing();
int mTickSpacing = 0;
if (mMinorTickSpacing > 0) {
mTickSpacing = mMinorTickSpacing;
} else if (mMajorTickSpacing > 0) {
mTickSpacing = mMajorTickSpacing;
}
if (mTickSpacing != 0) {
double mDoubleTickSpacing = cMinorTickSpacing > 0 ? cMinorTickSpacing : cMajorTickSpacing;
int mWhichTick = Math.round((float) value / (float) mTickSpacing);
mValue = mWhichTick * mDoubleTickSpacing + cMinimum;
}
}
return mValue;
}
/**
* Add an action listener.
*
* @param actionListener The action listener
*/
public void addActionListener(IActionListener actionListener) {
listenerList.add(IActionListener.class, actionListener);
}
/**
* Removes an action listener.
*
* @param actionListener The action listener
*/
public void removeActionListener(IActionListener actionListener) {
listenerList.remove(IActionListener.class, actionListener);
}
/**
* Fires an action event.
*/
void fireActionEvent() {
Object[] mListeners = listenerList.getListenerList();
for (int i = mListeners.length - 2; i >= 0; i -= 2) {
if (mListeners[i] == IActionListener.class) {
((IActionListener) mListeners[i + 1]).actionPerformed(this);
}
}
}
public void setBounds(Rectangle r) {
super.setBounds(r);
updateUI();
}
public boolean contains(Point2D p, AffineTransform t, GraphicHelper graphicHelper, float zoomFactor, boolean zoomEnabled) {
if (isOpaque()) {
Shape mShape = graphicHelper.getShape();
return mShape.contains(p);
}
float mFontSize = getFont().getSize2D();
float mComponentHeight = 24;
Point2D mTopLeft = graphicHelper.getXYNull();
Point2D mBottomLeft = graphicHelper.getXYHeight();
Point2D mTopRight = graphicHelper.getXYWidth();
Point2D mBottomRight = graphicHelper.getXYWidthHeight();
float mDefinitionHeight = isVertical() ? (float) mTopLeft.distance(mTopRight)
: (float) mTopLeft.distance(mBottomLeft);
float mComponentToDefinitionRatio = ((mComponentHeight / mDefinitionHeight) / 2f) * zoomFactor;
float mHeightOffSet = getPaintLabels() ? mFontSize / 2.0f + 4f : 0f;
if (!zoomEnabled && t != null) {
float mViewZoom = (float) t.getScaleX();
mComponentToDefinitionRatio /= mViewZoom;
mHeightOffSet /= mViewZoom;
}
mComponentToDefinitionRatio = Math.min(mComponentToDefinitionRatio, 0.5f);
float mHigh = (0.5f + mComponentToDefinitionRatio);
float mLow = (0.5f - mComponentToDefinitionRatio);
Point2D mNewTopLeft;
Point2D mNewBottomLeft;
Point2D mNewTopRight;
Point2D mNewBottomRight;
if (isVertical()) {
mNewTopLeft = new Point2D.Double(mTopLeft.getX() + ((mTopRight.getX() - mTopLeft.getX()) * mLow) - mHeightOffSet,
mTopLeft.getY() + ((mTopRight.getY() - mTopLeft.getY()) * mLow));
mNewTopRight = new Point2D.Double(mTopLeft.getX() + ((mTopRight.getX() - mTopLeft.getX()) * mHigh) - mHeightOffSet,
mTopLeft.getY() + ((mTopRight.getY() - mTopLeft.getY()) * mHigh));
mNewBottomLeft = new Point2D.Double(mBottomLeft.getX() + ((mBottomRight.getX() - mBottomLeft.getX()) * mLow) - mHeightOffSet,
mBottomLeft.getY() + ((mBottomRight.getY() - mBottomLeft.getY()) * mLow));
mNewBottomRight = new Point2D.Double(mBottomLeft.getX() + ((mBottomRight.getX() - mBottomLeft.getX()) * mHigh) - mHeightOffSet,
mBottomLeft.getY() + ((mBottomRight.getY() - mBottomLeft.getY()) * mHigh));
} else {
mNewTopLeft = new Point2D.Double(mTopLeft.getX() + ((mBottomLeft.getX() - mTopLeft.getX()) * mLow),
mTopLeft.getY() + ((mBottomLeft.getY() - mTopLeft.getY()) * mLow) - mHeightOffSet);
mNewBottomLeft = new Point2D.Double(mTopLeft.getX() + ((mBottomLeft.getX() - mTopLeft.getX()) * mHigh),
mTopLeft.getY() + ((mBottomLeft.getY() - mTopLeft.getY()) * mHigh) - mHeightOffSet);
mNewTopRight = new Point2D.Double(mTopRight.getX() + ((mBottomRight.getX() - mTopRight.getX()) * mLow),
mTopRight.getY() + ((mBottomRight.getY() - mTopRight.getY()) * mLow) - mHeightOffSet);
mNewBottomRight = new Point2D.Double(mTopRight.getX() + ((mBottomRight.getX() - mTopRight.getX()) * mHigh),
mTopRight.getY() + ((mBottomRight.getY() - mTopRight.getY()) * mHigh) - mHeightOffSet);
}
Path2D.Double mShape = new Path2D.Double(Path2D.WIND_NON_ZERO, 4);
mShape.moveTo(mNewTopLeft.getX(), mNewTopLeft.getY());
mShape.lineTo(mNewTopRight.getX(), mNewTopRight.getY());
mShape.lineTo(mNewBottomRight.getX(), mNewBottomRight.getY());
mShape.lineTo(mNewBottomLeft.getX(), mNewBottomLeft.getY());
return mShape.contains(p);
}
}