package de.geolykt.starloader.api.gui.graph; import java.util.Objects; import java.util.function.IntSupplier; import javax.annotation.Nonnegative; import org.jetbrains.annotations.ApiStatus.AvailableSince; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import de.geolykt.starloader.api.dimension.Empire; import de.geolykt.starloader.api.empire.Alliance; import de.geolykt.starloader.api.gui.Drawing; import de.geolykt.starloader.api.gui.DrawingImpl; import de.geolykt.starloader.api.gui.canvas.CanvasContext; import de.geolykt.starloader.api.gui.canvas.CanvasManager; import de.geolykt.starloader.api.gui.canvas.CanvasSettings; import de.geolykt.starloader.api.gui.canvas.prefab.AbstractResizeableCanvasContext; import de.geolykt.starloader.api.gui.screen.ScreenComponent; import de.geolykt.starloader.api.serial.references.PersistentEmpireReference; /** * A visualisation of a {@link ChartData} instance as a simple line chart. * *
This is the {@link CanvasContext} equivalent of the {@link LineChart} class * which uses the {@link ScreenComponent} API instead. In a similar vein, this * class is safe to subclass, however unlike {@link LineChart} this class * can be resized freely, within the bounds of {@link AbstractResizeableCanvasContext}. * *
Also, unlike {@link LineChart}, this component has no margins built-in. * If margins are desired in your code, use * {@link CanvasManager#withMargins(int, int, int, int, de.geolykt.starloader.api.gui.canvas.Canvas)}. * In other words, instances of this class will completely fill their alloted * space. * *
Further unlike {@link LineChart}, this component does not render any background by default. * Instead, use an appropriate {@link CanvasSettings} instance for background rendering, though * the exact value depends on how one chose to nest their canvases. For simple canvases * without any children, {@link CanvasSettings#DEFAULT_SEMISOLID} ought to be enough though. * *
Remember that the {@link ChartData} instance must allow reads from the UI thread.
* Failures to obey will not be caught by SLAPI, but may result in crashes within SLAPI code.
*
* @since 2.0.0-a20251222
* @param Line thickness can be set by calling {@link #setLineThickness(float)} on the constructed object.
*
* @param width The width of the component.
* @param height The height of the component.
* @param chart The {@link ChartData} to plot.
* @since 2.0.0-a20251222
*/
@Contract(pure = true)
@AvailableSince("2.0.0-a20251222")
public LineChartCanvasContext(@Nonnegative int width, @Nonnegative int height, @NotNull ChartData Line thickness can be set by calling {@link #setLineThickness(float)} on the constructed object.
*
* @param width The width of the component, see {@link #setWidth(IntSupplier)}.
* @param height The height of the component, see {@link #setHeight(IntSupplier)}.
* @param chart The {@link ChartData} to plot.
* @since 2.0.0-a20251222
*/
@Contract(pure = true)
@AvailableSince("2.0.0-a20251222")
public LineChartCanvasContext(@NotNull IntSupplier width, @NotNull IntSupplier height, @NotNull ChartData This method may be overridden by API consumers to provide custom vertex colouring.
*
* @param element The vertex element
* @return The color for the vertex element.
* @since 2.0.0-a20251222
*/
@SuppressWarnings("deprecation")
@NotNull
@Contract(pure = true)
@AvailableSince("2.0.0-a20251222")
protected Color getColor(@NotNull E element) {
if (element instanceof PersistentEmpireReference) {
return ((PersistentEmpireReference) element).getGdxColor();
} else if (element instanceof Empire) {
return ((Empire) element).getMapColor();
} else if (element instanceof de.geolykt.starloader.api.empire.Empire) {
return ((de.geolykt.starloader.api.empire.Empire) element).getGDXColor();
} else if (element instanceof Alliance) {
return ((Alliance) element).getGDXColor();
} else if (element instanceof Color) {
return (Color) element;
} else {
Color c = new Color(element.hashCode());
c.a = 1.0F;
return c;
}
}
/**
* Obtains the current thickness of lines of this {@link LineChartCanvasContext} instance.
*
* The default value is 2.
*
* @return The current line thickness.
* @since 2.0.0-a20251222
*/
@Contract(pure = true)
@AvailableSince("2.0.0-a20251222")
public float getLineThickness() {
return this.lineThickness;
}
@Override
public void render(@NotNull SpriteBatch surface, @NotNull Camera camera) {
final float componentHeight = this.getHeight();
final float componentWidth = this.getWidth();
final float pixelsPerValue = componentHeight / this.chart.getHeight();
final float pixelsPerIntervall = componentWidth / this.chart.getWidth();
final float thickness = this.lineThickness;
final DrawingImpl graphics = Drawing.getInstance();
for (ValueEdge The default value is 2.
*
* @param lineThickness The new line thickness to use.
* @since 2.0.0-a20251222
*/
@NotNull
@Contract(pure = false, mutates = "this", value = "_ -> this")
@AvailableSince("2.0.0-a20251222")
public LineChartCanvasContext