Not easy option is to enable inverse()
operation on axes. Without patching JRE classes it is quite complicated.
Some hints on how to approach this:
1) extend ValueAxis or Axis (NumberAxis is final unfortunately)
2) add boolean field and inverse()
method to your axis class
public void inverse() {
inversed = !inversed; // boolean property
invalidateRange();
requestAxisLayout();
}
3) if you extend ValueAxis - you will need to compensate the offset applied by the superclass (and intercept the code where the size of the axis is changing)
@Override
public Long getValueForDisplay(double displayPosition) {
if (inversed)
return super.getValueForDisplay(offset - displayPosition);
else
return super.getValueForDisplay(displayPosition);
}
@Override
public double getDisplayPosition(Long value) {
if (inversed)
return offset - super.getDisplayPosition(value);
else
return super.getDisplayPosition(value);
}
4) (the ugliest piece) un-hide label ticks suppressed by Axis class - the original implementation depends on default order of ticks. I did not find any other way other that unlock it via reflection. So this is very brittle.
@Override
protected void layoutChildren() {
final Side side = getSide();
boolean isHorisontal = null == side || side.isHorizontal();
this.offset = isHorisontal ? getWidth() : getHeight();
super.layoutChildren();
if (inversed) {
double prevEnd = isHorisontal ? offset + getTickLabelGap() : 0;
for (TickMark m : getTickMarks()) {
double position = m.getPosition();
try {
final Text textNode = (Text) textNodeField.get(m);
final Bounds bounds = textNode.getLayoutBounds();
if (0 <= position && position <= offset)
if (isHorisontal) {
textNode.setVisible(position < prevEnd);
prevEnd = position - (bounds.getWidth() + getTickLabelGap());
} else {
textNode.setVisible(position > prevEnd);
prevEnd = position + (bounds.getHeight() + getTickLabelGap());
}
} catch (IllegalAccessException ignored) {
}
}
}
}
Y Axis is inverted in this example