chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:47:05 +08:00
commit 4f3b7da785
7394 changed files with 2005594 additions and 0 deletions
@@ -0,0 +1,51 @@
## Developer Readme
Some things to know regarding the deeplearning4j-ui-components module:
- This module is designed with the following goals in mind:
- Providing easy Java/JavaScript interoperability for reusable user interface components (charts, tables etc)
- Maintainability via the use of TypeScript and proper OO design
- Rapid application development, rather than providing the greatest amount of power/flexibility
The directory/package and file structure is mirrored (as much as possible) on both the java and typescript sides.
Some design principles here:
- Content and style are separate
- The goal is to have style information as an *optional* component on the Java side
- In principle styling can be done entirely in Java, entirely in JavaScript/CSS, or via a mixture of both (style options defined in Java will override those defined in CSS)
- In both the Java and TypeScript, there are Style objects; these define properties such as colors or line widths
- Java objects for UI components are created; these are converted to JSON using Jackson (typically to be posted to a web server)
- Jackson is configured to ignore null elements when encoding JSON (and the TypeScript code should handle missing values)
- JSON is converted back into JavaScript/TypeScript objects using the Component.getComponent(jsonStr: string) method, or using the TS object constructors directly (i.e., these parse the JSON)
- Consequently, any changes made to the Java UI component classes should be mirrored in both the Java and TS code
- After the JS/TS versions of the UI objects are created, they can be added to an existing component using the .render(addToObject: JQuery) method
- For charts, d3.js is used
- At present: behaviour (on click events, etc) cannot be defined in Java (this has to be done in TS/JS)
**Setup for developing TypeScript code**
- Install [node.js](https://nodejs.org/en/) and [TypeScript compiler](https://www.typescriptlang.org/#download-links)
- Then, in IntelliJ
- Ensure auto-compilation to TypeScript is disabled (untick "Enable TypeScript Compiler" in File -> Settings -> Languages & Frameworks -> TypeScript)
- Install the File Watchers plugin (File -> Settings -> Plugins). This will enable auto compilation to a *single* javascript library any time you make a change to the .ts files (next step)
- Set up a new file watcher for compilation
- File -> Settings -> Tools -> File Watchers; (+) -> TypeScript
- Program: point to typescript compiler (on Windows, for example: "C:\Users\ *UserName* \AppData\Roaming\npm\tsc.cmd")
- Arguments: empty (empty: use tsconfig.json)
After the above setup, all TypeScript files will be compiled to a single javascript file.
(Make sure your TypeScript compiler version is up to date; tsconfig.json is only suported by version 1.5 or above)
- Location: /deeplearning4j-ui-components/src/main/resources/assets/dl4j-ui.js
- A source map file (dl4j-ui.js.map) will also be produced; this aids with debugging (can see/debug original typescript code, even after it is converted to JavaScript)
- File name, location, and other options are defined in the tsconfig.json
**Note:** A rendering test is available in *test.java.org.deeplearning4j.ui.TestRendering.java* that generates a HTML file with some sample graphs.
It is recommended to open this via IntelliJ (right click -> Open In Browser)
**Note 2:** The *src/main/typescript/typedefs/* folder contains type definitions for some javascript libraries, from [https://github.com/DefinitelyTyped/DefinitelyTyped](DefinitelyTyped).
These allow us to use javascript libraries in typescript, whilst having type information.
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ /* ******************************************************************************
~ *
~ *
~ * This program and the accompanying materials are made available under the
~ * terms of the Apache License, Version 2.0 which is available at
~ * https://www.apache.org/licenses/LICENSE-2.0.
~ *
~ * See the NOTICE file distributed with this work for additional
~ * information regarding copyright ownership.
~ * Unless required by applicable law or agreed to in writing, software
~ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
~ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
~ * License for the specific language governing permissions and limitations
~ * under the License.
~ *
~ * SPDX-License-Identifier: Apache-2.0
~ ******************************************************************************/
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.deeplearning4j</groupId>
<artifactId>deeplearning4j-ui-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>deeplearning4j-ui-components</artifactId>
<properties>
<module.name>deeplearning4j.ui.components</module.name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.moditect</groupId>
<artifactId>moditect-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<!-- ND4J Shaded Jackson Dependency -->
<dependency>
<groupId>org.eclipse.deeplearning4j</groupId>
<artifactId>jackson</artifactId>
<version>${nd4j.version}</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>${junit.platform.launcher.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commonsio.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.deeplearning4j</groupId>
<artifactId>nd4j-common</artifactId>
<version>${nd4j.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.deeplearning4j</groupId>
<artifactId>deeplearning4j-common-tests</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,56 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.api;
import lombok.Data;
import org.deeplearning4j.ui.components.chart.*;
import org.deeplearning4j.ui.components.component.ComponentDiv;
import org.deeplearning4j.ui.components.decorator.DecoratorAccordion;
import org.deeplearning4j.ui.components.table.ComponentTable;
import org.deeplearning4j.ui.components.text.ComponentText;
import org.nd4j.shade.jackson.annotation.JsonSubTypes;
import org.nd4j.shade.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes(value = {@JsonSubTypes.Type(value = ChartHistogram.class, name = "ChartHistogram"),
@JsonSubTypes.Type(value = ChartHorizontalBar.class, name = "ChartHorizontalBar"),
@JsonSubTypes.Type(value = ChartLine.class, name = "ChartLine"),
@JsonSubTypes.Type(value = ChartScatter.class, name = "ChartScatter"),
@JsonSubTypes.Type(value = ChartStackedArea.class, name = "ChartStackedArea"),
@JsonSubTypes.Type(value = ChartTimeline.class, name = "ChartTimeline"),
@JsonSubTypes.Type(value = ComponentDiv.class, name = "ComponentDiv"),
@JsonSubTypes.Type(value = DecoratorAccordion.class, name = "DecoratorAccordion"),
@JsonSubTypes.Type(value = ComponentTable.class, name = "ComponentTable"),
@JsonSubTypes.Type(value = ComponentText.class, name = "ComponentText")})
@Data
public abstract class Component {
/** Component type: used by the Arbiter UI to determine how to decode and render the object which is
* represented by the JSON representation of this object*/
protected final String componentType;
protected final Style style;
public Component(String componentType, Style style) {
this.componentType = componentType;
this.style = style;
}
}
@@ -0,0 +1,25 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.api;
public enum LengthUnit {
Px, Percent, CM, MM, In
}
@@ -0,0 +1,129 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.api;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.deeplearning4j.ui.components.chart.style.StyleChart;
import org.deeplearning4j.ui.components.component.style.StyleDiv;
import org.deeplearning4j.ui.components.decorator.style.StyleAccordion;
import org.deeplearning4j.ui.components.table.style.StyleTable;
import org.deeplearning4j.ui.components.text.style.StyleText;
import org.nd4j.shade.jackson.annotation.JsonSubTypes;
import org.nd4j.shade.jackson.annotation.JsonTypeInfo;
import java.awt.*;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes(value = {@JsonSubTypes.Type(value = StyleChart.class, name = "StyleChart"),
@JsonSubTypes.Type(value = StyleTable.class, name = "StyleTable"),
@JsonSubTypes.Type(value = StyleText.class, name = "StyleText"),
@JsonSubTypes.Type(value = StyleAccordion.class, name = "StyleAccordion"),
@JsonSubTypes.Type(value = StyleDiv.class, name = "StyleDiv")})
@Data
@AllArgsConstructor
@NoArgsConstructor
public abstract class Style {
private Double width;
private Double height;
private LengthUnit widthUnit;
private LengthUnit heightUnit;
protected LengthUnit marginUnit;
protected Double marginTop;
protected Double marginBottom;
protected Double marginLeft;
protected Double marginRight;
protected String backgroundColor;
public Style(Builder b) {
this.width = b.width;
this.height = b.height;
this.widthUnit = b.widthUnit;
this.heightUnit = b.heightUnit;
this.marginUnit = b.marginUnit;
this.marginTop = b.marginTop;
this.marginBottom = b.marginBottom;
this.marginLeft = b.marginLeft;
this.marginRight = b.marginRight;
this.backgroundColor = b.backgroundColor;
}
@SuppressWarnings("unchecked")
public static abstract class Builder<T extends Builder<T>> {
protected Double width;
protected Double height;
protected LengthUnit widthUnit;
protected LengthUnit heightUnit;
protected LengthUnit marginUnit;
protected Double marginTop;
protected Double marginBottom;
protected Double marginLeft;
protected Double marginRight;
protected String backgroundColor;
public T width(double width, LengthUnit widthUnit) {
this.width = width;
this.widthUnit = widthUnit;
return (T) this;
}
public T height(double height, LengthUnit heightUnit) {
this.height = height;
this.heightUnit = heightUnit;
return (T) this;
}
public T margin(LengthUnit unit, Integer marginTop, Integer marginBottom, Integer marginLeft,
Integer marginRight) {
return margin(unit, (marginTop != null ? marginTop.doubleValue() : null),
(marginBottom != null ? marginBottom.doubleValue() : null),
(marginLeft != null ? marginLeft.doubleValue() : null),
(marginRight != null ? marginRight.doubleValue() : null));
}
public T margin(LengthUnit unit, Double marginTop, Double marginBottom, Double marginLeft, Double marginRight) {
this.marginUnit = unit;
this.marginTop = marginTop;
this.marginBottom = marginBottom;
this.marginLeft = marginLeft;
this.marginRight = marginRight;
return (T) this;
}
public T backgroundColor(Color color) {
return backgroundColor(Utils.colorToHex(color));
}
public T backgroundColor(String color) {
this.backgroundColor = color;
return (T) this;
}
}
}
@@ -0,0 +1,34 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.api;
import java.awt.*;
public class Utils {
private Utils() {}
/** Convert an AWT color to a hex color string, such as #000000 */
public static String colorToHex(Color color) {
return String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue());
}
}
@@ -0,0 +1,179 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.chart;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.deeplearning4j.ui.api.Component;
import org.deeplearning4j.ui.components.chart.style.StyleChart;
import org.nd4j.shade.jackson.annotation.JsonInclude;
@Data
@EqualsAndHashCode(callSuper = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public abstract class Chart extends Component {
private String title;
private Boolean suppressAxisHorizontal;
private Boolean suppressAxisVertical;
private boolean showLegend;
private Double setXMin;
private Double setXMax;
private Double setYMin;
private Double setYMax;
private Double gridVerticalStrokeWidth;
private Double gridHorizontalStrokeWidth;
public Chart(String componentType) {
super(componentType, null);
}
public Chart(String componentType, Builder builder) {
super(componentType, builder.getStyle());
this.title = builder.title;
this.suppressAxisHorizontal = builder.suppressAxisHorizontal;
this.suppressAxisVertical = builder.suppressAxisVertical;
this.showLegend = builder.showLegend;
this.setXMin = builder.setXMin;
this.setXMax = builder.setXMax;
this.setYMin = builder.setYMin;
this.setYMax = builder.setYMax;
this.gridVerticalStrokeWidth = builder.gridVerticalStrokeWidth;
this.gridHorizontalStrokeWidth = builder.gridHorizontalStrokeWidth;
}
@Getter
@SuppressWarnings("unchecked")
public static abstract class Builder<T extends Builder<T>> {
private String title;
private StyleChart style;
private Boolean suppressAxisHorizontal;
private Boolean suppressAxisVertical;
private boolean showLegend;
private Double setXMin;
private Double setXMax;
private Double setYMin;
private Double setYMax;
private Double gridVerticalStrokeWidth;
private Double gridHorizontalStrokeWidth;
/**
* @param title Title for the chart (may be null)
* @param style Style for the chart (may be null)
*/
public Builder(String title, StyleChart style) {
this.title = title;
this.style = style;
}
/**
* @param suppressAxisHorizontal if true: don't show the horizontal axis (default: show)
*/
public T suppressAxisHorizontal(boolean suppressAxisHorizontal) {
this.suppressAxisHorizontal = suppressAxisHorizontal;
return (T) this;
}
/**
* @param suppressAxisVertical if true: don't show the vertical axis (default: show)
*/
public T suppressAxisVertical(boolean suppressAxisVertical) {
this.suppressAxisVertical = suppressAxisVertical;
return (T) this;
}
/**
* @param showLegend if true: show the legend. (default: no legend)
*/
public T showLegend(boolean showLegend) {
this.showLegend = showLegend;
return (T) this;
}
/**
* Used to override/set the minimum value for the x axis. If this is not set, x axis minimum is set based on the data
* @param xMin Minimum value to use for the x axis
*/
public T setXMin(Double xMin) {
this.setXMin = xMin;
return (T) this;
}
/**
* Used to override/set the maximum value for the x axis. If this is not set, x axis maximum is set based on the data
* @param xMax Maximum value to use for the x axis
*/
public T setXMax(Double xMax) {
this.setXMax = xMax;
return (T) this;
}
/**
* Used to override/set the minimum value for the y axis. If this is not set, y axis minimum is set based on the data
* @param yMin Minimum value to use for the y axis
*/
public T setYMin(Double yMin) {
this.setYMin = yMin;
return (T) this;
}
/**
* Used to override/set the maximum value for the y axis. If this is not set, y axis minimum is set based on the data
* @param yMax Minimum value to use for the y axis
*/
public T setYMax(Double yMax) {
this.setYMax = yMax;
return (T) this;
}
/**
* Set the grid lines to be enabled, and if enabled: set the grid.
* @param gridVerticalStrokeWidth If null (or 0): show no vertical grid. Otherwise: width in px
* @param gridHorizontalStrokeWidth If null (or 0): show no horizontal grid. Otherwise: width in px
*/
public T setGridWidth(Double gridVerticalStrokeWidth, Double gridHorizontalStrokeWidth) {
this.gridVerticalStrokeWidth = gridVerticalStrokeWidth;
this.gridHorizontalStrokeWidth = gridHorizontalStrokeWidth;
return (T) this;
}
/**
* Set the grid lines to be enabled, and if enabled: set the grid.
* @param gridVerticalStrokeWidth If null (or 0): show no vertical grid. Otherwise: width in px
* @param gridHorizontalStrokeWidth If null (or 0): show no horizontal grid. Otherwise: width in px
*/
public T setGridWidth(Integer gridVerticalStrokeWidth, Integer gridHorizontalStrokeWidth) {
return setGridWidth((gridVerticalStrokeWidth != null ? gridVerticalStrokeWidth.doubleValue() : null),
(gridHorizontalStrokeWidth != null ? gridHorizontalStrokeWidth.doubleValue() : null));
}
}
}
@@ -0,0 +1,107 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.chart;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.deeplearning4j.ui.components.chart.style.StyleChart;
import org.nd4j.shade.jackson.annotation.JsonInclude;
import java.util.ArrayList;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ChartHistogram extends Chart {
public static final String COMPONENT_TYPE = "ChartHistogram";
private List<Double> lowerBounds = new ArrayList<>();
private List<Double> upperBounds = new ArrayList<>();
private List<Double> yValues = new ArrayList<>();
public ChartHistogram(Builder builder) {
super(COMPONENT_TYPE, builder);
this.lowerBounds = builder.lowerBounds;
this.upperBounds = builder.upperBounds;
this.yValues = builder.yValues;
}
//No arg constructor for Jackson
public ChartHistogram() {
super(COMPONENT_TYPE);
}
public static class Builder extends Chart.Builder<Builder> {
private List<Double> lowerBounds = new ArrayList<>();
private List<Double> upperBounds = new ArrayList<>();
private List<Double> yValues = new ArrayList<>();
public Builder(String title, StyleChart style) {
super(title, style);
}
/**
* Add a single bin
*
* @param lower Lower (minimum/left) value for the bin (x axis)
* @param upper Upper (maximum/right) value for the bin (x axis)
* @param yValue The height of the bin
*/
public Builder addBin(double lower, double upper, double yValue) {
lowerBounds.add(lower);
upperBounds.add(upper);
yValues.add(yValue);
return this;
}
public ChartHistogram build() {
return new ChartHistogram(this);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ChartHistogram(lowerBounds=");
if (lowerBounds != null) {
sb.append(lowerBounds);
} else {
sb.append("[]");
}
sb.append(",upperBounds=");
if (upperBounds != null) {
sb.append(upperBounds);
} else {
sb.append("[]");
}
sb.append(",yValues=");
if (yValues != null) {
sb.append(yValues);
} else {
sb.append("[]");
}
sb.append(")");
return sb.toString();
}
}
@@ -0,0 +1,126 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.chart;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.deeplearning4j.ui.components.chart.style.StyleChart;
import org.nd4j.shade.jackson.annotation.JsonInclude;
import java.util.ArrayList;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ChartHorizontalBar extends Chart {
public static final String COMPONENT_TYPE = "ChartHorizontalBar";
private List<String> labels = new ArrayList<>();
private List<Double> values = new ArrayList<>();
private Double xmin;
private Double xmax;
private ChartHorizontalBar(Builder builder) {
super(COMPONENT_TYPE, builder);
labels = builder.labels;
values = builder.values;
this.xmin = builder.xMin;
this.xmax = builder.xMax;
}
public ChartHorizontalBar() {
super(COMPONENT_TYPE, null);
//no-arg constructor for Jackson
}
public static class Builder extends Chart.Builder<Builder> {
private List<String> labels = new ArrayList<>();
private List<Double> values = new ArrayList<>();
private Double xMin;
private Double xMax;
public Builder(String title, StyleChart style) {
super(title, style);
}
public Builder addValue(String name, double value) {
labels.add(name);
values.add(value);
return this;
}
public Builder addValues(List<String> names, double[] values) {
for (int i = 0; i < names.size(); i++) {
addValue(names.get(i), values[i]);
}
return this;
}
public Builder xMin(double xMin) {
this.xMin = xMin;
return this;
}
public Builder xMax(double xMax) {
this.xMax = xMax;
return this;
}
public Builder addValues(List<String> names, float[] values) {
for (int i = 0; i < names.size(); i++) {
addValue(names.get(i), values[i]);
}
return this;
}
public ChartHorizontalBar build() {
return new ChartHorizontalBar(this);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ChartHorizontalBar(labels=");
if (labels != null) {
sb.append(labels);
} else {
sb.append("[]");
}
sb.append(",values=");
if (values != null) {
sb.append(values);
} else {
sb.append("[]");
}
if (xmin != null)
sb.append(",xMin=").append(xmin);
if (xmax != null)
sb.append(",xMax=").append(xmax);
sb.append(")");
return sb.toString();
}
}
@@ -0,0 +1,109 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.chart;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.deeplearning4j.ui.components.chart.style.StyleChart;
import org.nd4j.shade.jackson.annotation.JsonInclude;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ChartLine extends Chart {
public static final String COMPONENT_TYPE = "ChartLine";
private List<double[]> x;
private List<double[]> y;
private List<String> seriesNames;
private ChartLine(Builder builder) {
super(COMPONENT_TYPE, builder);
x = builder.x;
y = builder.y;
seriesNames = builder.seriesNames;
}
public ChartLine() {
super(COMPONENT_TYPE);
//no-arg constructor for Jackson
}
public static class Builder extends Chart.Builder<Builder> {
private List<double[]> x = new ArrayList<>();
private List<double[]> y = new ArrayList<>();
private List<String> seriesNames = new ArrayList<>();
private boolean showLegend = true;
public Builder(String title, StyleChart style) {
super(title, style);
}
public Builder addSeries(String seriesName, double[] xValues, double[] yValues) {
x.add(xValues);
y.add(yValues);
seriesNames.add(seriesName);
return this;
}
public ChartLine build() {
return new ChartLine(this);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ChartLine(x=[");
boolean first = true;
if (x != null) {
for (double[] d : x) {
if (!first)
sb.append(",");
sb.append(Arrays.toString(d));
first = false;
}
}
sb.append("],y=[");
first = true;
if (y != null) {
for (double[] d : y) {
if (!first)
sb.append(",");
sb.append(Arrays.toString(d));
first = false;
}
}
sb.append("],seriesNames=");
if (seriesNames != null)
sb.append(seriesNames);
sb.append(")");
return sb.toString();
}
}
@@ -0,0 +1,114 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.chart;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.deeplearning4j.ui.components.chart.style.StyleChart;
import org.nd4j.shade.jackson.annotation.JsonInclude;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ChartScatter extends Chart {
public static final String COMPONENT_TYPE = "ChartScatter";
private List<double[]> x;
private List<double[]> y;
private List<String> seriesNames;
private ChartScatter(Builder builder) {
super(COMPONENT_TYPE, builder);
x = builder.x;
y = builder.y;
seriesNames = builder.seriesNames;
}
public ChartScatter() {
super(COMPONENT_TYPE);
//no-arg constructor for Jackson
}
public static class Builder extends Chart.Builder<Builder> {
private List<double[]> x = new ArrayList<>();
private List<double[]> y = new ArrayList<>();
private List<String> seriesNames = new ArrayList<>();
public Builder(String title, StyleChart style) {
super(title, style);
}
/**
*
* @param seriesName Name of the series
* @param xValues Array of x values
* @param yValues Array of y values (such that a single point i has coordinates (x[i],y[i]))
* @return
*/
public Builder addSeries(String seriesName, double[] xValues, double[] yValues) {
x.add(xValues);
y.add(yValues);
seriesNames.add(seriesName);
return this;
}
public ChartScatter build() {
return new ChartScatter(this);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ChartScatter(x=[");
boolean first = true;
if (x != null) {
for (double[] d : x) {
if (!first)
sb.append(",");
sb.append(Arrays.toString(d));
first = false;
}
}
sb.append("],y=[");
first = true;
if (y != null) {
for (double[] d : y) {
if (!first)
sb.append(",");
sb.append(Arrays.toString(d));
first = false;
}
}
sb.append("],seriesNames=");
if (seriesNames != null)
sb.append(seriesNames);
sb.append(")");
return sb.toString();
}
}
@@ -0,0 +1,115 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.chart;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.deeplearning4j.ui.components.chart.style.StyleChart;
import org.nd4j.shade.jackson.annotation.JsonInclude;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ChartStackedArea extends Chart {
public static final String COMPONENT_TYPE = "ChartStackedArea";
private double[] x = new double[0];
private List<double[]> y = new ArrayList<>();
private List<String> labels = new ArrayList<>();
public ChartStackedArea() {
super(COMPONENT_TYPE);
}
public ChartStackedArea(Builder builder) {
super(COMPONENT_TYPE, builder);
this.x = builder.x;
this.y = builder.y;
this.labels = builder.seriesNames;
}
public static class Builder extends Chart.Builder<Builder> {
private double[] x;
private List<double[]> y = new ArrayList<>();
private List<String> seriesNames = new ArrayList<>();
public Builder(String title, StyleChart style) {
super(title, style);
}
/**
* Set the x-axis values
*/
public Builder setXValues(double[] x) {
this.x = x;
return this;
}
/**
* Add a single series.
*
* @param seriesName Name of the series
* @param yValues length of the yValues array must be same as the x-values array
*/
public Builder addSeries(String seriesName, double[] yValues) {
y.add(yValues);
seriesNames.add(seriesName);
return this;
}
public ChartStackedArea build() {
return new ChartStackedArea(this);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ChartStackedArea(x=");
if (x != null) {
sb.append(Arrays.toString(x));
} else {
sb.append("[]");
}
sb.append(",y=[");
boolean first = true;
if (y != null) {
for (double[] d : y) {
if (!first)
sb.append(",");
sb.append(Arrays.toString(d));
first = false;
}
}
sb.append("],labels=");
if (labels != null)
sb.append(labels);
sb.append(")");
return sb.toString();
}
}
@@ -0,0 +1,103 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.chart;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.deeplearning4j.ui.api.Utils;
import org.deeplearning4j.ui.components.chart.style.StyleChart;
import org.nd4j.shade.jackson.annotation.JsonInclude;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ChartTimeline extends Chart {
public static final String COMPONENT_TYPE = "ChartTimeline";
private List<String> laneNames = new ArrayList<>();
private List<List<TimelineEntry>> laneData = new ArrayList<>();
public ChartTimeline() {
super(COMPONENT_TYPE);
//no-arg constructor for Jackson
}
private ChartTimeline(Builder builder) {
super(COMPONENT_TYPE, builder);
this.laneNames = builder.laneNames;
this.laneData = builder.laneData;
}
public static class Builder extends Chart.Builder<Builder> {
private List<String> laneNames = new ArrayList<>();
private List<List<TimelineEntry>> laneData = new ArrayList<>();
public Builder(String title, StyleChart style) {
super(title, style);
}
public Builder addLane(String name, List<TimelineEntry> data) {
laneNames.add(name);
laneData.add(data);
return this;
}
public ChartTimeline build() {
return new ChartTimeline(this);
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class TimelineEntry {
private String entryLabel;
private long startTimeMs;
private long endTimeMs;
private String color;
public TimelineEntry(String entryLabel, long startTimeMs, long endTimeMs) {
this.entryLabel = entryLabel;
this.startTimeMs = startTimeMs;
this.endTimeMs = endTimeMs;
}
public TimelineEntry(String entryLabel, long startTimeMs, long endTimeMs, Color color) {
this.entryLabel = entryLabel;
this.startTimeMs = startTimeMs;
this.endTimeMs = endTimeMs;
this.color = Utils.colorToHex(color);
}
}
}
@@ -0,0 +1,116 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.chart.style;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.deeplearning4j.ui.api.Style;
import org.deeplearning4j.ui.api.Utils;
import org.deeplearning4j.ui.components.text.style.StyleText;
import org.nd4j.shade.jackson.annotation.JsonInclude;
import java.awt.*;
@AllArgsConstructor
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class StyleChart extends Style {
public static final Double DEFAULT_CHART_MARGIN_TOP = 60.0;
public static final Double DEFAULT_CHART_MARGIN_BOTTOM = 20.0;
public static final Double DEFAULT_CHART_MARGIN_LEFT = 60.0;
public static final Double DEFAULT_CHART_MARGIN_RIGHT = 20.0;
protected Double strokeWidth;
protected Double pointSize;
protected String[] seriesColors;
protected Double axisStrokeWidth;
protected StyleText titleStyle;
private StyleChart(Builder b) {
super(b);
this.strokeWidth = b.strokeWidth;
this.pointSize = b.pointSize;
this.seriesColors = b.seriesColors;
this.axisStrokeWidth = b.axisStrokeWidth;
this.titleStyle = b.titleStyle;
}
public static class Builder extends Style.Builder<Builder> {
protected Double strokeWidth;
protected Double pointSize;
protected String[] seriesColors;
protected Double axisStrokeWidth;
protected StyleText titleStyle;
public Builder() {
super.marginTop = DEFAULT_CHART_MARGIN_TOP;
super.marginBottom = DEFAULT_CHART_MARGIN_BOTTOM;
super.marginLeft = DEFAULT_CHART_MARGIN_LEFT;
super.marginRight = DEFAULT_CHART_MARGIN_RIGHT;
}
public Builder strokeWidth(double strokeWidth) {
this.strokeWidth = strokeWidth;
return this;
}
/** Point size, for scatter plot etc */
public Builder pointSize(double pointSize) {
this.pointSize = pointSize;
return this;
}
public Builder seriesColors(Color... colors) {
String[] str = new String[colors.length];
for (int i = 0; i < str.length; i++)
str[i] = Utils.colorToHex(colors[i]);
return seriesColors(str);
}
public Builder seriesColors(String... colors) {
this.seriesColors = colors;
return this;
}
public Builder axisStrokeWidth(double axisStrokeWidth) {
this.axisStrokeWidth = axisStrokeWidth;
return this;
}
public Builder titleStyle(StyleText style) {
this.titleStyle = style;
return this;
}
public StyleChart build() {
return new StyleChart(this);
}
}
}
@@ -0,0 +1,53 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.component;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.deeplearning4j.ui.api.Component;
import org.deeplearning4j.ui.api.Style;
import org.nd4j.shade.jackson.annotation.JsonInclude;
import java.util.Collection;
@Data
@EqualsAndHashCode(callSuper = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ComponentDiv extends Component {
public static final String COMPONENT_TYPE = "ComponentDiv";
private Component[] components;
public ComponentDiv() {
super(COMPONENT_TYPE, null);
}
public ComponentDiv(Style style, Component... components) {
super(COMPONENT_TYPE, style);
this.components = components;
}
public ComponentDiv(Style style, Collection<Component> componentCollection) {
this(style, (componentCollection == null ? null
: componentCollection.toArray(new Component[componentCollection.size()])));
}
}
@@ -0,0 +1,63 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.component.style;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.deeplearning4j.ui.api.Style;
import org.nd4j.shade.jackson.annotation.JsonInclude;
@NoArgsConstructor
@Data
@EqualsAndHashCode(callSuper = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class StyleDiv extends Style {
/** Enumeration: possible values for float style option */
public enum FloatValue {
non, left, right, initial, inherit
}
private FloatValue floatValue;
private StyleDiv(Builder builder) {
super(builder);
this.floatValue = builder.floatValue;
}
public static class Builder extends Style.Builder<Builder> {
private FloatValue floatValue;
/** CSS float styling option */
public Builder floatValue(FloatValue floatValue) {
this.floatValue = floatValue;
return this;
}
public StyleDiv build() {
return new StyleDiv(this);
}
}
}
@@ -0,0 +1,99 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.decorator;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.deeplearning4j.ui.api.Component;
import org.deeplearning4j.ui.components.decorator.style.StyleAccordion;
import org.nd4j.shade.jackson.annotation.JsonInclude;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class DecoratorAccordion extends Component {
public static final String COMPONENT_TYPE = "DecoratorAccordion";
private String title;
private boolean defaultCollapsed;
private Component[] innerComponents;
public DecoratorAccordion() {
super(COMPONENT_TYPE, null);
//No arg constructor for Jackson
}
private DecoratorAccordion(Builder builder) {
super(COMPONENT_TYPE, builder.style);
this.title = builder.title;
this.defaultCollapsed = builder.defaultCollapsed;
this.innerComponents = builder.innerComponents.toArray(new Component[builder.innerComponents.size()]);
}
public static class Builder {
private StyleAccordion style;
private String title;
private List<Component> innerComponents = new ArrayList<>();
private boolean defaultCollapsed;
public Builder(StyleAccordion style) {
this(null, style);
}
public Builder(String title, StyleAccordion style) {
this.title = title;
this.style = style;
}
public Builder title(String title) {
this.title = title;
return this;
}
/**
* Components to show internally in the accordion element
*/
public Builder addComponents(Component... innerComponents) {
Collections.addAll(this.innerComponents, innerComponents);
return this;
}
/**
* Set the default collapsed/expanded state
*
* @param defaultCollapsed If true: default to collapsed
*/
public Builder setDefaultCollapsed(boolean defaultCollapsed) {
this.defaultCollapsed = defaultCollapsed;
return this;
}
public DecoratorAccordion build() {
return new DecoratorAccordion(this);
}
}
}
@@ -0,0 +1,50 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.decorator.style;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.deeplearning4j.ui.api.Style;
import org.nd4j.shade.jackson.annotation.JsonInclude;
@NoArgsConstructor
@Data
@EqualsAndHashCode(callSuper = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class StyleAccordion extends Style {
private StyleAccordion(Builder builder) {
super(builder);
}
public static class Builder extends Style.Builder<Builder> {
public StyleAccordion build() {
return new StyleAccordion(this);
}
}
}
@@ -0,0 +1,90 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.deeplearning4j.ui.api.Component;
import org.deeplearning4j.ui.components.table.style.StyleTable;
import org.nd4j.shade.jackson.annotation.JsonInclude;
@EqualsAndHashCode(callSuper = true)
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ComponentTable extends Component {
public static final String COMPONENT_TYPE = "ComponentTable";
private String title;
private String[] header;
private String[][] content;
public ComponentTable() {
super(COMPONENT_TYPE, null);
//No arg constructor for Jackson
}
public ComponentTable(Builder builder) {
super(COMPONENT_TYPE, builder.style);
this.header = builder.header;
this.content = builder.content;
}
public ComponentTable(String[] header, String[][] table, StyleTable style) {
super(COMPONENT_TYPE, style);
this.header = header;
this.content = table;
}
public static class Builder {
private StyleTable style;
private String[] header;
private String[][] content;
public Builder(StyleTable style) {
this.style = style;
}
/**
* @param header Header values for the table
*/
public Builder header(String... header) {
this.header = header;
return this;
}
/**
* Content for the table, as 2d String[]
*/
public Builder content(String[][] content) {
this.content = content;
return this;
}
public ComponentTable build() {
return new ComponentTable(this);
}
}
}
@@ -0,0 +1,143 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.table.style;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.deeplearning4j.ui.api.LengthUnit;
import org.deeplearning4j.ui.api.Style;
import org.deeplearning4j.ui.api.Utils;
import org.nd4j.shade.jackson.annotation.JsonInclude;
import java.awt.*;
@Data
@EqualsAndHashCode(callSuper = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class StyleTable extends Style {
private double[] columnWidths;
private LengthUnit columnWidthUnit;
private Integer borderWidthPx;
private String headerColor;
private String backgroundColor;
private String whitespaceMode;
private StyleTable(Builder builder) {
super(builder);
this.columnWidths = builder.columnWidths;
this.columnWidthUnit = builder.columnWidthUnit;
this.borderWidthPx = builder.borderWidthPx;
this.headerColor = builder.headerColor;
this.backgroundColor = builder.backgroundColor;
this.whitespaceMode = builder.whitespaceMode;
}
//No arg constructor for Jackson
private StyleTable() {
}
public static class Builder extends Style.Builder<Builder> {
private double[] columnWidths;
private LengthUnit columnWidthUnit;
private Integer borderWidthPx;
private String headerColor;
private String backgroundColor;
private String whitespaceMode;
/**
* Specify the widths for the columns
*
* @param unit Unit that the widths are specified in
* @param widths Width values for the columns
*/
public Builder columnWidths(LengthUnit unit, double... widths) {
this.columnWidthUnit = unit;
this.columnWidths = widths;
return this;
}
/**
* @param borderWidthPx Width of the border, in px
*/
public Builder borderWidth(int borderWidthPx) {
this.borderWidthPx = borderWidthPx;
return this;
}
/**
* @param color Background color for the header row
*/
public Builder headerColor(Color color) {
String hex = Utils.colorToHex(color);
return headerColor(hex);
}
/**
* @param color Background color for the header row
*/
public Builder headerColor(String color) {
if (!color.toLowerCase().matches("#[a-f0-9]{6}"))
throw new IllegalArgumentException("Invalid color: must be hex format. Got: " + color);
this.headerColor = color;
return this;
}
/**
* @param color Background color for the table cells (ex. header row)
*/
public Builder backgroundColor(Color color) {
String hex = Utils.colorToHex(color);
return backgroundColor(hex);
}
/**
* @param color Background color for the table cells (ex. header row)
*/
public Builder backgroundColor(String color) {
if (!color.toLowerCase().matches("#[a-f0-9]{6}"))
throw new IllegalArgumentException("Invalid color: must be hex format. Got: " + color);
this.backgroundColor = color;
return this;
}
/**
* Set the whitespace mode (CSS style tag). For example, "pre" to maintain current formatting with no wrapping,
* "pre-wrap" to wrap (but otherwise take into account new line characters in text, etc)
*
* @param whitespaceMode CSS whitespace mode
*/
public Builder whitespaceMode(String whitespaceMode) {
this.whitespaceMode = whitespaceMode;
return this;
}
public StyleTable build() {
return new StyleTable(this);
}
}
}
@@ -0,0 +1,72 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.text;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.deeplearning4j.ui.api.Component;
import org.deeplearning4j.ui.components.text.style.StyleText;
import org.nd4j.shade.jackson.annotation.JsonInclude;
@EqualsAndHashCode(callSuper = true)
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ComponentText extends Component {
public static final String COMPONENT_TYPE = "ComponentText";
private String text;
public ComponentText() {
super(COMPONENT_TYPE, null);
//No arg constructor for Jackson deserialization
text = null;
}
public ComponentText(String text, StyleText style) {
super(COMPONENT_TYPE, style);
this.text = text;
}
private ComponentText(Builder builder) {
this(builder.text, builder.style);
}
@Override
public String toString() {
return "ComponentText(" + text + ")";
}
public static class Builder {
private StyleText style;
private String text;
public Builder(String text, StyleText style) {
this.text = text;
this.style = style;
}
public ComponentText build() {
return new ComponentText(this);
}
}
}
@@ -0,0 +1,111 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.components.text.style;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.deeplearning4j.ui.api.Style;
import org.deeplearning4j.ui.api.Utils;
import org.nd4j.shade.jackson.annotation.JsonInclude;
import java.awt.*;
/**
* Style for text
*/
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class StyleText extends Style {
private String font;
private Double fontSize;
private Boolean underline;
private String color;
private Boolean whitespacePre;
private StyleText(Builder builder) {
super(builder);
this.font = builder.font;
this.fontSize = builder.fontSize;
this.underline = builder.underline;
this.color = builder.color;
this.whitespacePre = builder.whitespacePre;
}
public static class Builder extends Style.Builder<Builder> {
private String font;
private Double fontSize;
private Boolean underline;
private String color;
private Boolean whitespacePre;
/** Specify the font to be used for the text */
public Builder font(String font) {
this.font = font;
return this;
}
/** Size of the font (pt) */
public Builder fontSize(double size) {
this.fontSize = size;
return this;
}
/** If true: text should be underlined (default: not) */
public Builder underline(boolean underline) {
this.underline = underline;
return this;
}
/** Color for the text */
public Builder color(Color color) {
return color(Utils.colorToHex(color));
}
/** Color for the text */
public Builder color(String color) {
this.color = color;
return this;
}
/**
* If set to true: add a "white-space: pre" to the style.
* In effect, this stops the representation from compressing the whitespace characters, and messing up/removing
* text that contains newlines, tabs, etc.
*/
public Builder whitespacePre(boolean whitespacePre) {
this.whitespacePre = whitespacePre;
return this;
}
public StyleText build() {
return new StyleText(this);
}
}
}
@@ -0,0 +1,33 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.standalone;
import lombok.AllArgsConstructor;
import lombok.Data;
@AllArgsConstructor
@Data
public class ComponentObject {
public final String id;
public final String content;
}
@@ -0,0 +1,129 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
package org.deeplearning4j.ui.standalone;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.Version;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.deeplearning4j.ui.api.Component;
import org.nd4j.common.io.ClassPathResource;
import org.nd4j.shade.jackson.databind.DeserializationFeature;
import org.nd4j.shade.jackson.databind.MapperFeature;
import org.nd4j.shade.jackson.databind.ObjectMapper;
import org.nd4j.shade.jackson.databind.SerializationFeature;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.*;
public class StaticPageUtil {
private StaticPageUtil() {}
/**
* Given the specified components, render them to a stand-alone HTML page (which is returned as a String)
*
* @param components Components to render
* @return Stand-alone HTML page, as a String
*/
public static String renderHTML(Collection<Component> components) {
return renderHTML(components.toArray(new Component[components.size()]));
}
/**
* Given the specified components, render them to a stand-alone HTML page (which is returned as a String)
*
* @param components Components to render
* @return Stand-alone HTML page, as a String
*/
public static String renderHTML(Component... components) {
try {
return renderHTMLContent(components);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static String renderHTMLContent(Component... components) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
mapper.enable(SerializationFeature.INDENT_OUTPUT);
Configuration cfg = new Configuration(new Version(2, 3, 23));
// Where do we load the templates from:
cfg.setClassForTemplateLoading(StaticPageUtil.class, "");
// Some other recommended settings:
cfg.setIncompatibleImprovements(new Version(2, 3, 23));
cfg.setDefaultEncoding("UTF-8");
cfg.setLocale(Locale.US);
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
ClassPathResource cpr = new ClassPathResource("assets/dl4j-ui.js");
String scriptContents = IOUtils.toString(cpr.getInputStream(), "UTF-8");
Map<String, Object> pageElements = new HashMap<>();
List<ComponentObject> list = new ArrayList<>();
int i = 0;
for (Component c : components) {
list.add(new ComponentObject(String.valueOf(i), mapper.writeValueAsString(c)));
i++;
}
pageElements.put("components", list);
pageElements.put("scriptcontent", scriptContents);
Template template = cfg.getTemplate("staticpage.ftl");
Writer stringWriter = new StringWriter();
template.process(pageElements, stringWriter);
return stringWriter.toString();
}
/**
* A version of {@link #renderHTML(Component...)} that exports the resulting HTML to the specified path.
*
* @param outputPath Output path
* @param components Components to render
*/
public static void saveHTMLFile(String outputPath, Component... components) throws IOException {
saveHTMLFile(new File(outputPath));
}
/**
* A version of {@link #renderHTML(Component...)} that exports the resulting HTML to the specified File.
*
* @param outputFile Output path
* @param components Components to render
*/
public static void saveHTMLFile(File outputFile, Component... components) throws IOException {
FileUtils.writeStringToFile(outputFile, renderHTML(components));
}
}
@@ -0,0 +1,19 @@
open module deeplearning4j.ui.components {
requires commons.io;
requires freemarker;
requires jackson;
requires nd4j.common;
requires java.desktop;
exports org.deeplearning4j.ui.api;
exports org.deeplearning4j.ui.components.chart;
exports org.deeplearning4j.ui.components.chart.style;
exports org.deeplearning4j.ui.components.component;
exports org.deeplearning4j.ui.components.component.style;
exports org.deeplearning4j.ui.components.decorator;
exports org.deeplearning4j.ui.components.decorator.style;
exports org.deeplearning4j.ui.components.table;
exports org.deeplearning4j.ui.components.table.style;
exports org.deeplearning4j.ui.components.text;
exports org.deeplearning4j.ui.components.text.style;
exports org.deeplearning4j.ui.standalone;
}
@@ -0,0 +1,130 @@
[
{
"name":"org.deeplearning4j.ui.components.chart.ChartHistogram",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.components.chart.Chart",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.components.chart.ChartHorizontalBar",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.components.chart.ChartLine",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.components.chart.ChartScatter",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.components.chart.ChartStackedArea",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.components.chart.ChartTimeline",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.api.Style",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.components.component.ComponentDiv",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.components.decorator.style.StyleAccordion",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.components.decorator.DecoratorAccordion",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.components.table.style.StyleTable",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.components.table.ComponentTable",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.components.text.style.StyleText",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.components.text.ComponentText",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name":"org.deeplearning4j.ui.api.Style",
"allDeclaredFields":true,
"allDeclaredMethods":true,
"allDeclaredConstructors":true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
}
]
@@ -0,0 +1,241 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
declare abstract class Style {
private width;
private height;
private widthUnit;
private heightUnit;
private marginTop;
private marginBottom;
private marginLeft;
private marginRight;
private backgroundColor;
constructor(jsonObj: any);
getWidth: () => number;
getHeight: () => number;
getWidthUnit: () => string;
getHeightUnit: () => string;
getMarginTop: () => number;
getMarginBottom: () => number;
getMarginLeft: () => number;
getMarginRight: () => number;
getBackgroundColor: () => string;
static getMargins(s: Style): Margin;
}
declare enum ComponentType {
ComponentText = 0,
ComponentTable = 1,
ComponentDiv = 2,
ChartHistogram = 3,
ChartHorizontalBar = 4,
ChartLine = 5,
ChartScatter = 6,
ChartStackedArea = 7,
ChartTimeline = 8,
DecoratorAccordion = 9,
}
declare abstract class Component {
private componentType;
constructor(componentType: ComponentType);
getComponentType(): ComponentType;
static getComponent(jsonStr: string): Renderable;
}
declare class ChartConstants {
static DEFAULT_CHART_STROKE_WIDTH: number;
static DEFAULT_CHART_POINT_SIZE: number;
static DEFAULT_AXIS_STROKE_WIDTH: number;
static DEFAULT_TITLE_COLOR: string;
}
interface Margin {
top: number;
right: number;
bottom: number;
left: number;
widthExMargins: number;
heightExMargins: number;
}
interface Renderable {
render: (addToObject: JQuery) => void;
}
declare class TSUtils {
static max(input: number[][]): number;
static min(input: number[][]): number;
static normalizeLengthUnit(input: string): string;
}
declare abstract class Chart extends Component {
protected style: StyleChart;
protected title: string;
protected suppressAxisHorizontal: boolean;
protected suppressAxisVertical: boolean;
protected showLegend: boolean;
protected setXMin: number;
protected setXMax: number;
protected setYMin: number;
protected setYMax: number;
protected gridVerticalStrokeWidth: number;
protected gridHorizontalStrokeWidth: number;
constructor(componentType: ComponentType, jsonStr: string);
getStyle(): StyleChart;
protected static appendTitle(svg: any, title: string, margin: Margin, titleStyle: StyleText): void;
}
declare class ChartHistogram extends Chart implements Renderable {
private lowerBounds;
private upperBounds;
private yValues;
constructor(jsonStr: string);
render: (appendToObject: JQuery) => void;
}
declare class ChartLine extends Chart implements Renderable {
private xData;
private yData;
private seriesNames;
constructor(jsonStr: string);
render: (appendToObject: JQuery) => void;
}
declare class ChartScatter extends Chart implements Renderable {
private xData;
private yData;
private seriesNames;
constructor(jsonStr: string);
render: (appendToObject: JQuery) => void;
}
declare class Legend {
private static offsetX;
private static offsetY;
private static padding;
private static separation;
private static boxSize;
private static fillColor;
private static legendOpacity;
private static borderStrokeColor;
static legendFn: (g: any) => void;
}
declare class ChartStackedArea extends Chart implements Renderable {
private xData;
private yData;
private labels;
constructor(jsonStr: string);
render: (appendToObject: JQuery) => void;
}
declare class ChartTimeline extends Chart implements Renderable {
private laneNames;
private laneData;
private lanes;
private itemData;
private mainView;
private miniView;
private brush;
private x;
private x1;
private xTimeAxis;
private y1;
private y2;
private itemRects;
private rect;
private static MINI_LANE_HEIGHT_PX;
private static ENTRY_LANE_HEIGHT_OFFSET_FRACTION;
private static ENTRY_LANE_HEIGHT_TOTAL_FRACTION;
private static MILLISEC_PER_MINUTE;
private static MILLISEC_PER_HOUR;
private static MILLISEC_PER_DAY;
private static MILLISEC_PER_WEEK;
private static DEFAULT_COLOR;
constructor(jsonStr: string);
render: (appendToObject: JQuery) => void;
renderChart: () => void;
moveBrush: () => void;
getMiniViewPaths: (items: any) => any[];
}
declare class StyleChart extends Style {
protected strokeWidth: number;
protected pointSize: number;
protected seriesColors: string[];
protected axisStrokeWidth: number;
protected titleStyle: StyleText;
constructor(jsonObj: any);
getStrokeWidth: () => number;
getPointSize: () => number;
getSeriesColors: () => string[];
getSeriesColor: (idx: number) => string;
getAxisStrokeWidth: () => number;
getTitleStyle: () => StyleText;
}
declare class ComponentDiv extends Component implements Renderable {
private style;
private components;
constructor(jsonStr: string);
render: (appendToObject: JQuery) => void;
}
declare class StyleDiv extends Style {
protected floatValue: string;
constructor(jsonObj: any);
getFloatValue: () => string;
}
declare class DecoratorAccordion extends Component implements Renderable {
private style;
private title;
private defaultCollapsed;
private innerComponents;
constructor(jsonStr: string);
render: (appendToObject: JQuery) => void;
}
declare class StyleAccordion extends Style {
constructor(jsonObj: any);
}
declare class ComponentTable extends Component implements Renderable {
private header;
private content;
private style;
constructor(jsonStr: string);
render: (appendToObject: JQuery) => void;
}
declare class StyleTable extends Style {
private columnWidths;
private columnWidthUnit;
private borderWidthPx;
private headerColor;
private whitespaceMode;
constructor(jsonObj: any);
getColumnWidths: () => number[];
getColumnWidthUnit: () => string;
getBorderWidthPx: () => number;
getHeaderColor: () => string;
getWhitespaceMode: () => string;
}
declare class ComponentText extends Component implements Renderable {
private text;
private style;
constructor(jsonStr: string);
render: (appendToObject: JQuery) => void;
}
declare class StyleText extends Style {
private font;
private fontSize;
private underline;
private color;
private whitespacePre;
constructor(jsonObj: any);
getFont: () => string;
getFontSize: () => number;
getUnderline: () => boolean;
getColor: () => string;
getWhitespacePre: () => boolean;
}
@@ -0,0 +1,72 @@
<html>
<head>
<style type="text/css">
html, body {
width: 100%;
height: 100%;
}
h1 {
font-family: Georgia, Times, 'Times New Roman', serif;
font-size: 28px;
font-style: bold;
font-variant: normal;
font-weight: 500;
line-height: 26.4px;
}
h3 {
font-family: Georgia, Times, 'Times New Roman', serif;
font-size: 16px;
font-style: normal;
font-variant: normal;
font-weight: 500;
line-height: 26.4px;
}
</style>
<title>Data Analysis</title>
</head>
<body style="padding: 0px; margin: 0px" onload="generateContent()">
<#--<meta name="viewport" content="width=device-width, initial-scale=1">-->
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<link href="http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script>
function generateContent(){
var mainDiv = $('#outerdiv');
<#list components as c>
var div_${c.id} = $('#${c.id}');
var html_${c.id} = div_${c.id}.html();
var component = Component.getComponent(html_${c.id});
component.render(mainDiv);
</#list>
}
</script>
<script>
${scriptcontent}
</script>
<div style="width:1400px; margin:0 auto; border:0px" id="outerdiv">
</div>
<#list components as c>
<div id="${c.id}" style="display:none">
${c.content}
</div>
</#list>
</body>
</html>
@@ -0,0 +1,86 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
abstract class Component {
private componentType: ComponentType;
constructor(componentType: ComponentType){
this.componentType = componentType;
}
public getComponentType(){
return this.componentType;
}
/* Parse the JSON string that represents a component, and build that component
* Assumption here: the format is like '{"ComponentTable": {...}}' - i.e., as generated by Jackson for the Java objects
* */
public static getComponent(jsonStr: string): Renderable {
var json: any = JSON.parse(jsonStr);
var key: string;
if(json["componentType"]) key = json["componentType"]; //No wrapper object case...
else key = Object.keys(json)[0]; //Typical wrapper object case
switch(key){
case ComponentType[ComponentType.ComponentText]:
return new ComponentText(jsonStr);
case ComponentType[ComponentType.ComponentTable]:
return new ComponentTable(jsonStr);
case ComponentType[ComponentType.ChartHistogram]:
return new ChartHistogram(jsonStr);
case ComponentType[ComponentType.ChartHorizontalBar]:
throw new Error("Horizontal bar chart: not yet implemented");
case ComponentType[ComponentType.ChartLine]:
return new ChartLine(jsonStr);
case ComponentType[ComponentType.ChartScatter]:
return new ChartScatter(jsonStr);
case ComponentType[ComponentType.ChartStackedArea]:
return new ChartStackedArea(jsonStr);
case ComponentType[ComponentType.ChartTimeline]:
return new ChartTimeline(jsonStr);
case ComponentType[ComponentType.DecoratorAccordion]:
return new DecoratorAccordion(jsonStr);
case ComponentType[ComponentType.ComponentDiv]:
return new ComponentDiv(jsonStr);
default:
throw new Error("Unknown component type \"" + key + "\" or invalid JSON: \"" + jsonStr + "\"");
}
}
}
@@ -0,0 +1,32 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
enum ComponentType {
ComponentText,
ComponentTable,
ComponentDiv,
ChartHistogram,
ChartHorizontalBar,
ChartLine,
ChartScatter,
ChartStackedArea,
ChartTimeline,
DecoratorAccordion
}
@@ -0,0 +1,27 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class ChartConstants {
static DEFAULT_CHART_STROKE_WIDTH = 1.0;
static DEFAULT_CHART_POINT_SIZE = 3.0;
static DEFAULT_AXIS_STROKE_WIDTH = 1.0;
static DEFAULT_TITLE_COLOR = "#000000";
}
@@ -0,0 +1,28 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
interface Margin {
top: number;
right: number;
bottom: number;
left: number;
widthExMargins: number;
heightExMargins: number;
}
@@ -0,0 +1,28 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
interface Renderable {
render: (addToObject: JQuery) => void;
//TODO: Implement an update method. Can be used to update an existing chart, table etc with new data,
// without redrawing the whole thing from scratch
//update: (jsonObj: any) => void;
}
@@ -0,0 +1,72 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
abstract class Style {
private width: number;
private height: number;
private widthUnit: string;
private heightUnit: string;
private marginTop: number;
private marginBottom: number;
private marginLeft: number;
private marginRight: number;
private backgroundColor: string;
constructor( jsonObj: any){
this.width = jsonObj['width'];
this.height = jsonObj['height'];
this.widthUnit = TSUtils.normalizeLengthUnit(jsonObj['widthUnit']);
this.heightUnit = TSUtils.normalizeLengthUnit(jsonObj['heightUnit']);
this.marginTop = jsonObj['marginTop'];
this.marginBottom = jsonObj['marginBottom'];
this.marginLeft = jsonObj['marginLeft'];
this.marginRight = jsonObj['marginRight'];
this.backgroundColor = jsonObj['backgroundColor'];
}
getWidth = () => this.width;
getHeight = () => this.height;
getWidthUnit = () => this.widthUnit;
getHeightUnit = () => this.heightUnit;
getMarginTop = () => this.marginTop;
getMarginBottom = () => this.marginBottom;
getMarginLeft = () => this.marginLeft;
getMarginRight = () => this.marginRight;
getBackgroundColor = () => this.backgroundColor;
static getMargins(s: Style): Margin{
var mTop: number = (s ? s.getMarginTop() : 0);
var mBottom: number = (s ? s.getMarginBottom() : 0);
var mLeft: number = (s ? s.getMarginLeft() : 0);
var mRight: number = (s ? s.getMarginRight() : 0);
// Set the dimensions of the canvas / graph
return {top: mTop,
right: mRight,
bottom: mBottom,
left: mLeft,
widthExMargins: s.getWidth() - mLeft - mRight,
heightExMargins: s.getHeight() - mTop - mBottom};
}
}
@@ -0,0 +1,83 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
abstract class Chart extends Component {
protected style: StyleChart;
protected title: string;
protected suppressAxisHorizontal: boolean;
protected suppressAxisVertical: boolean;
protected showLegend: boolean;
protected setXMin: number;
protected setXMax: number;
protected setYMin: number;
protected setYMax: number;
protected gridVerticalStrokeWidth: number;
protected gridHorizontalStrokeWidth: number;
constructor(componentType: ComponentType, jsonStr: string){
super(componentType);
var jsonOrig: any = JSON.parse(jsonStr);
var json = JSON.parse(jsonStr);
if(!json["componentType"]) json = json[ComponentType[componentType]]; //Usually: expect type as wrapper object
this.suppressAxisHorizontal = json['suppressAxisHorizontal'];
this.suppressAxisVertical = json['suppressAxisVertical'];
this.showLegend = json['showLegend'];
this.title = json['title'];
this.setXMin = json['setXMin'];
this.setXMax = json['setXMax'];
this.setYMin = json['setYMin'];
this.setYMax = json['setYMax'];
this.gridVerticalStrokeWidth = json['gridVerticalStrokeWidth'];
this.gridHorizontalStrokeWidth = json['gridHorizontalStrokeWidth'];
if(json['style']) this.style = new StyleChart(json['style']);
}
getStyle(): StyleChart {
return this.style;
}
protected static appendTitle(svg: any, title: string, margin: Margin, titleStyle: StyleText): void{
var text = svg.append("text")
.text(title)
.attr("x", (margin.widthExMargins / 2))
.attr("y", 0 - ((margin.top - 30) / 2))
.attr("text-anchor", "middle");
if(titleStyle){
if(titleStyle.getFont()) text.attr("font-family",titleStyle.getFont);
if(titleStyle.getFontSize() != null) text.attr("font-size",titleStyle.getFontSize()+"pt");
if(titleStyle.getUnderline() != null) text.style("text-decoration", "underline");
if(titleStyle.getColor()) text.style("fill",titleStyle.getColor);
else text.style("fill",ChartConstants.DEFAULT_TITLE_COLOR);
} else {
text.style("text-decoration", "underline");
text.style("fill",ChartConstants.DEFAULT_TITLE_COLOR);
}
}
}
@@ -0,0 +1,147 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class ChartHistogram extends Chart implements Renderable {
private lowerBounds: number[];
private upperBounds: number[];
private yValues: number[];
constructor(jsonStr: string){
super(ComponentType.ChartHistogram, jsonStr);
var json = JSON.parse(jsonStr);
if(!json["componentType"]) json = json[ComponentType[ComponentType.ChartHistogram]];
this.lowerBounds = json['lowerBounds'];
this.upperBounds = json['upperBounds'];
this.yValues = json['yvalues'];
}
render = (appendToObject: JQuery) => {
var s: StyleChart = this.getStyle();
var margin: Margin = Style.getMargins(s);
// Add the bins.
var xMin: number;
var xMax: number;
var yMin: number;
var yMax: number;
if(this.setXMin) xMin = this.setXMin;
else xMin = (this.lowerBounds ? d3.min(this.lowerBounds) : 0);
if(this.setXMax) xMax = this.setXMax;
else xMax = (this.upperBounds ? d3.max(this.upperBounds) : 1);
if(this.setYMin) yMin = this.setYMin;
else yMin = 0;
if(this.setYMax) yMax = this.setYMax;
else yMax = (this.yValues ? d3.max(this.yValues) : 1);
//// Define the axes
var xScale: any = d3.scale.linear()
.domain([xMin, xMax])
.range([0, margin.widthExMargins]);
var xAxis: any = d3.svg.axis().scale(xScale)
.orient("bottom").ticks(5);
if(this.gridVerticalStrokeWidth && this.gridVerticalStrokeWidth > 0){
xAxis.innerTickSize(-margin.heightExMargins); //used as grid line
}
var yScale: any = d3.scale.linear()
.domain([0, yMax])
.range([margin.heightExMargins, 0]);
var yAxis: any = d3.svg.axis().scale(yScale)
.orient("left").ticks(5);
if(this.gridHorizontalStrokeWidth && this.gridHorizontalStrokeWidth > 0){
yAxis.innerTickSize(-margin.widthExMargins); //used as grid line
}
if(this.suppressAxisHorizontal === true) xAxis.tickValues([]);
if(this.suppressAxisVertical === true) yAxis.tickValues([]);
// Set up the data:
var lowerBounds: number[] = this.lowerBounds;
var upperBounds: number[] = this.upperBounds;
var yValues: number[] = this.yValues;
var data: any = lowerBounds.map(function (d, i) {
return {'width': upperBounds[i] - lowerBounds[i], 'height': yValues[i], 'offset': lowerBounds[i]};
});
// Adds the svg canvas
var svg = d3.select("#" + appendToObject.attr("id"))
.append("svg")
.style("fill", "none")
.attr("width", s.getWidth())
.attr("height", s.getHeight())
.attr("padding", "20px")
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
svg.selectAll(".bin")
.data(data)
.enter().append("rect")
.attr("class", "bin")
.style("fill","steelblue")
.attr("x", function(d: any) { return xScale(d.offset); })
.attr("width", function(d: any) { return xScale(xMin + d.width) - 1; })
.attr("y", function(d: any) { return yScale(d.height); })
.attr("height", function(d: any) { return margin.heightExMargins - yScale(d.height); });
// Add the X Axis
var xAxisNode = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + margin.heightExMargins + ")")
.style("stroke","#000")
.style("stroke-width", (s != null && s.getAxisStrokeWidth() != null ? s.getAxisStrokeWidth() : ChartConstants.DEFAULT_AXIS_STROKE_WIDTH))
.style("fill","none")
.call(xAxis);
xAxisNode.selectAll('text').style("stroke-width",0).style("fill","#000000");
if(this.gridVerticalStrokeWidth != null) xAxisNode.selectAll('.axis line').style({'stroke-width': this.gridVerticalStrokeWidth});
// Add the Y Axis
var yAxisNode = svg.append("g")
.attr("class", "y axis")
.style("stroke","#000")
.style("stroke-width", (s != null && s.getAxisStrokeWidth() != null ? s.getAxisStrokeWidth() : ChartConstants.DEFAULT_AXIS_STROKE_WIDTH))
.style("fill","none")
.call(yAxis);
yAxisNode.selectAll('text').style("stroke-width",0).style("fill","#000000");
if(this.gridHorizontalStrokeWidth != null) yAxisNode.selectAll('.axis line').style({'stroke-width': this.gridHorizontalStrokeWidth});
//Add title (if present)
if (this.title) {
var titleStyle: StyleText;
if(this.style) titleStyle = this.style.getTitleStyle();
Chart.appendTitle(svg, this.title, margin, titleStyle);
}
}
}
@@ -0,0 +1,167 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class ChartLine extends Chart implements Renderable {
private xData: number[][];
private yData: number[][];
private seriesNames: string[];
constructor(jsonStr: string){
super(ComponentType.ChartLine, jsonStr);
var json = JSON.parse(jsonStr);
if(!json["componentType"]) json = json[ComponentType[ComponentType.ChartLine]];
this.xData = json['x'];
this.yData = json['y'];
this.seriesNames = json['seriesNames'];
}
render = (appendToObject: JQuery) => {
var nSeries: number = (!this.xData ? 0 : this.xData.length);
var s: StyleChart = this.getStyle();
var margin: Margin = Style.getMargins(s);
// Set the ranges
var xScale: d3.scale.Linear<number,number> = d3.scale.linear().range([0, margin.widthExMargins]);
var yScale: d3.scale.Linear<number,number> = d3.scale.linear().range([margin.heightExMargins, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(xScale)
.orient("bottom").ticks(5);
if(this.gridVerticalStrokeWidth != null && this.gridVerticalStrokeWidth > 0){
xAxis.innerTickSize(-margin.heightExMargins); //used as grid line
}
var yAxis = d3.svg.axis().scale(yScale)
.orient("left").ticks(5);
if(this.gridHorizontalStrokeWidth != null && this.gridHorizontalStrokeWidth > 0){
yAxis.innerTickSize(-margin.widthExMargins); //used as grid line
}
if(this.suppressAxisHorizontal === true) xAxis.tickValues([]);
if(this.suppressAxisVertical === true) yAxis.tickValues([]);
// Define the line
var valueline = d3.svg.line()
.x(function (d: any) {
return xScale(d.xPos);
})
.y(function (d: any) {
return yScale(d.yPos);
});
// Adds the svg canvas
//TODO don't hardcode these colors/attributes...
var svg = d3.select("#" + appendToObject.attr("id"))
.append("svg")
.style("stroke-width", ( s && s.getStrokeWidth() ? s.getStrokeWidth() : ChartConstants.DEFAULT_CHART_STROKE_WIDTH))
.style("fill", "none")
.attr("width", s.getWidth())
.attr("height", s.getHeight())
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Scale the range of the chart
var xMin: number;
var xMax: number;
var yMin: number;
var yMax: number;
if(this.setXMin != null) xMin = this.setXMin;
else xMin = (this.xData ? TSUtils.min(this.xData) : 0);
if(this.setXMax != null) xMax = this.setXMax;
else xMax = (this.xData ? TSUtils.max(this.xData) : 1);
if(this.setYMin != null) yMin = this.setYMin;
else yMin = (this.yData ? TSUtils.min(this.yData) : 0);
if(this.setYMax != null) yMax = this.setYMax;
else yMax = (this.yData ? TSUtils.max(this.yData) : 1);
xScale.domain([xMin, xMax]);
yScale.domain([yMin, yMax]);
// Add the valueline path.
var defaultColor: Ordinal<string,string> = d3.scale.category10();
for (var i = 0; i < nSeries; i++) {
var xVals: number[] = this.xData[i];
var yVals: number[] = this.yData[i];
var data: any[] = xVals.map(function (d, i) {
return {'xPos': xVals[i], 'yPos': yVals[i]};
});
svg.append("path")
.attr("class", "line")
.style("stroke", (s && s.getSeriesColor(i) ? s.getSeriesColor(i) : defaultColor(String(i))))
.attr("d", valueline(data));
}
// Add the X Axis
var xAxisNode = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + margin.heightExMargins + ")")
.style("stroke","#000")
.style("stroke-width", (s != null && s.getAxisStrokeWidth() != null ? s.getAxisStrokeWidth() : ChartConstants.DEFAULT_AXIS_STROKE_WIDTH))
.style("fill","none")
.call(xAxis);
xAxisNode.selectAll('text').style("stroke-width",0).style("fill","#000000");
if(this.gridVerticalStrokeWidth != null) xAxisNode.selectAll('.axis line').style({'stroke-width': this.gridVerticalStrokeWidth});
// Add the Y Axis
var yAxisNode = svg.append("g")
.attr("class", "y axis")
.style("stroke","#000")
.style("stroke-width", (s != null && s.getAxisStrokeWidth() != null ? s.getAxisStrokeWidth() : ChartConstants.DEFAULT_AXIS_STROKE_WIDTH))
.style("fill","none")
.call(yAxis);
yAxisNode.selectAll('text').style("stroke-width",0).style("fill","#000000");
if(this.gridHorizontalStrokeWidth != null) yAxisNode.selectAll('.axis line').style({'stroke-width': this.gridHorizontalStrokeWidth});
//Add legend (if present)
if (this.seriesNames && this.showLegend === true) {
var legendSpace = margin.widthExMargins / i;
for (var i = 0; i < nSeries; i++) {
var values = this.xData[i];
var yValues = this.yData[i];
var lastX = values[values.length - 1];
var lastY = yValues[yValues.length - 1];
var toDisplay = this.seriesNames[i];
svg.append("text")
.attr("x", (legendSpace / 2) + i * legendSpace) // spacing
.attr("y", margin.heightExMargins + (margin.bottom / 2) + 5)
.attr("class", "legend") // style the legend
.style("fill", (s && s.getSeriesColor(i) ? s.getSeriesColor(i) : defaultColor(String(i))))
.text(toDisplay);
}
}
//Add title (if present)
if (this.title) {
var titleStyle: StyleText;
if(this.style) titleStyle = this.style.getTitleStyle();
Chart.appendTitle(svg, this.title, margin, titleStyle);
}
}
}
@@ -0,0 +1,165 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class ChartScatter extends Chart implements Renderable {
private xData:number[][];
private yData:number[][];
private seriesNames:string[];
constructor(jsonStr:string) {
super(ComponentType.ChartScatter, jsonStr);
var json = JSON.parse(jsonStr);
if(!json["componentType"]) json = json[ComponentType[ComponentType.ChartScatter]];
this.xData = json['x'];
this.yData = json['y'];
this.seriesNames = json['seriesNames'];
}
render = (appendToObject:JQuery) => {
var nSeries:number = (!this.xData ? 0 : this.xData.length);
var s:StyleChart = this.getStyle();
var margin:Margin = Style.getMargins(s);
// Set the ranges
var xScale:d3.scale.Linear<number,number> = d3.scale.linear().range([0, margin.widthExMargins]);
var yScale:d3.scale.Linear<number,number> = d3.scale.linear().range([margin.heightExMargins, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(xScale)
.innerTickSize(-margin.heightExMargins) //used as grid line
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(yScale)
.innerTickSize(-margin.widthExMargins) //used as grid line
.orient("left").ticks(5);
if (this.suppressAxisHorizontal === true) xAxis.tickValues([]);
if (this.suppressAxisVertical === true) yAxis.tickValues([]);
// Adds the svg canvas
//TODO don't hardcode these colors/attributes...
var svg = d3.select("#" + appendToObject.attr("id"))
.append("svg")
.style("stroke-width", ( s && s.getStrokeWidth() ? s.getStrokeWidth() : 1))
.style("fill", "none")
.attr("width", s.getWidth())
.attr("height", s.getHeight())
.attr("padding", "20px")
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Scale the range of the chart
var xMin:number;
var xMax:number;
var yMin:number;
var yMax:number;
if (this.setXMin) xMin = this.setXMin;
else xMin = (this.xData ? TSUtils.min(this.xData) : 0);
if (this.setXMax) xMax = this.setXMax;
else xMax = (this.xData ? TSUtils.max(this.xData) : 1);
if (this.setYMin) yMin = this.setYMin;
else yMin = (this.yData ? TSUtils.min(this.yData) : 0);
if (this.setYMax) yMax = this.setYMax;
else yMax = (this.yData ? TSUtils.max(this.yData) : 1);
xScale.domain([xMin, xMax]);
yScale.domain([yMin, yMax]);
// Add the valueline path.
var defaultColor:Ordinal<string,string> = d3.scale.category10();
for (var i = 0; i < nSeries; i++) {
var xVals = this.xData[i];
var yVals = this.yData[i];
var data = xVals.map(function (d, i) {
return {'xPos': xVals[i], 'yPos': yVals[i]};
});
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.style("fill", (s && s.getSeriesColor(i) ? s.getSeriesColor(i) : defaultColor(String(i))))
.attr("r", (s && s.getPointSize() ? s.getPointSize() : ChartConstants.DEFAULT_CHART_POINT_SIZE))
.attr("cx", function (d) {
return xScale(d['xPos']);
})
.attr("cy", function (d) {
return yScale(d['yPos']);
});
}
// Add the X Axis
var xAxisNode = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + margin.heightExMargins + ")")
.style("stroke", "#000")
.style("stroke-width", (s != null && s.getAxisStrokeWidth() != null ? s.getAxisStrokeWidth() : ChartConstants.DEFAULT_AXIS_STROKE_WIDTH))
.style("fill", "none")
.call(xAxis);
xAxisNode.selectAll('text').style("stroke-width",0).style("fill","#000000");
if (this.gridVerticalStrokeWidth != null) xAxisNode.selectAll('.axis line').style({'stroke-width': this.gridVerticalStrokeWidth});
// Add the Y Axis
var yAxisNode = svg.append("g")
.attr("class", "y axis")
.style("stroke", "#000")
.style("stroke-width", (s != null && s.getAxisStrokeWidth() != null ? s.getAxisStrokeWidth() : ChartConstants.DEFAULT_AXIS_STROKE_WIDTH))
.style("fill", "none")
.call(yAxis);
yAxisNode.selectAll('text').style("stroke-width",0).style("fill","#000000");
if (this.gridHorizontalStrokeWidth != null) yAxisNode.selectAll('.axis line').style({'stroke-width': this.gridHorizontalStrokeWidth});
//Add legend (if present)
if (this.seriesNames && this.showLegend === true) {
var legendSpace = margin.widthExMargins / i;
for (var i = 0; i < nSeries; i++) {
var values = this.xData[i];
var yValues = this.yData[i];
var lastX = values[values.length - 1];
var lastY = yValues[yValues.length - 1];
var toDisplay;
if (!lastX || !lastY) toDisplay = this.seriesNames[i] + " (no data)";
else toDisplay = this.seriesNames[i] + " (" + lastX.toPrecision(5) + "," + lastY.toPrecision(5) + ")";
svg.append("text")
.attr("x", (legendSpace / 2) + i * legendSpace) // spacing
.attr("y", margin.heightExMargins + (margin.bottom / 2) + 5)
.attr("class", "legend") // style the legend
.style("fill", (s && s.getSeriesColor(i) ? s.getSeriesColor(i) : defaultColor(String(i))))
.text(toDisplay);
}
}
//Add title (if present)
if (this.title) {
var titleStyle: StyleText;
if(this.style) titleStyle = this.style.getTitleStyle();
Chart.appendTitle(svg, this.title, margin, titleStyle);
}
}
}
@@ -0,0 +1,176 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class ChartStackedArea extends Chart implements Renderable {
private xData: number[];
private yData: number[][];
private labels: string[];
constructor(jsonStr: string){
super(ComponentType.ChartStackedArea, jsonStr);
var json = JSON.parse(jsonStr);
if(!json["componentType"]) json = json[ComponentType[ComponentType.ChartStackedArea]];
this.xData = json['x'];
this.yData = json['y'];
this.labels = json['labels'];
}
render = (appendToObject: JQuery) => {
var nSeries: number = (!this.xData ? 0 : this.xData.length);
var s: StyleChart = this.getStyle();
var margin: Margin = Style.getMargins(s);
// Set the ranges
var xScale: d3.scale.Linear<number,number> = d3.scale.linear().range([0, margin.widthExMargins]);
var yScale: d3.scale.Linear<number,number> = d3.scale.linear().range([margin.heightExMargins, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(xScale)
.orient("bottom").ticks(5);
if(this.gridVerticalStrokeWidth != null && this.gridVerticalStrokeWidth > 0){
xAxis.innerTickSize(-margin.heightExMargins); //used as grid line
}
var yAxis = d3.svg.axis().scale(yScale)
.orient("left").ticks(5);
if(this.gridHorizontalStrokeWidth != null && this.gridHorizontalStrokeWidth > 0){
yAxis.innerTickSize(-margin.widthExMargins); //used as grid line
}
if(this.suppressAxisHorizontal === true) xAxis.tickValues([]);
if(this.suppressAxisVertical === true) yAxis.tickValues([]);
var data: any[] = [];
for(var i=0; i<this.xData.length; i++ ){
var obj = {};
for( var j=0; j<this.labels.length; j++ ){
obj[this.labels[j]] = this.yData[j][i];
obj['xValue'] = this.xData[i];
}
data.push(obj);
}
var area = d3.svg.area()
.x(function(d: any) { return xScale(d.xValue); })
.y0(function(d: any) { return yScale(d.y0); })
.y1(function(d: any) { return yScale(d.y0 + d.y); });
var stack = d3.layout.stack()
.values(function(d: any) { return d.values; });
var svg = d3.select("#" + appendToObject.attr("id")).append("svg")
.attr("width", margin.widthExMargins + margin.left + margin.right)
.attr("height", margin.heightExMargins + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var color: any = d3.scale.category20();
color.domain(d3.keys(data[0]).filter(function (key) {
return key !== "xValue";
}));
var browsers = stack(color.domain().map(function (name) {
return {
name: name,
values: data.map(function (d) {
return {xValue: d.xValue, y: d[name] * 1};
})
};
}));
// Find the value of the day with highest total value
var maxX = d3.max(data, function (d) {
var vals = d3.keys(d).map(function (key) {
return key !== "xValue" ? d[key] : 0
});
return d3.sum(vals);
});
// Set domains for axes
xScale.domain(d3.extent(data, function (d) {
return d.xValue;
}));
yScale.domain([0, maxX]);
var browser = svg.selectAll(".browser")
.data(browsers)
.enter().append("g")
.attr("class", "browser");
var tempLabels = this.labels;
var defaultColor: Ordinal<string,string> = d3.scale.category20();
browser.append("path")
.attr("class", "area")
.attr("data-legend",function(d: any) { return d.name})
.attr("d", function (d: any) {
return area(d.values);
})
.style("fill", function(d: any){
if(s && s.getSeriesColor(tempLabels.indexOf(d.name))){
return s.getSeriesColor(tempLabels.indexOf(d.name));
} else{
return defaultColor(String(tempLabels.indexOf(d.name)))
}
})
.style({"stroke-width": "0px"});
//Add the x axis:
var xAxisNode = svg.append("g")
.attr("class", "x axis")
.style("stroke","#000")
.style("stroke-width", (s != null && s.getAxisStrokeWidth() != null ? s.getAxisStrokeWidth() : ChartConstants.DEFAULT_AXIS_STROKE_WIDTH))
.style("fill","none")
.attr("transform", "translate(0," + margin.heightExMargins + ")")
.call(xAxis);
xAxisNode.selectAll('text').style("stroke-width",0).style("fill","#000000");
//Add the y axis
var yAxisNode = svg.append("g")
.attr("class", "y axis")
.style("stroke","#000")
.style("stroke-width", (s != null && s.getAxisStrokeWidth() != null ? s.getAxisStrokeWidth() : ChartConstants.DEFAULT_AXIS_STROKE_WIDTH))
.style("fill","none")
.call(yAxis);
yAxisNode.selectAll('text').style("stroke-width",0).style("fill","#000000");
//Add title (if present)
if (this.title) {
var titleStyle: StyleText;
if(this.style) titleStyle = this.style.getTitleStyle();
Chart.appendTitle(svg, this.title, margin, titleStyle);
}
//Append the legend
var legend: any = svg.append("g")
.attr("class","legend")
.attr("transform","translate(40,40)")
.style("font-size","12px")
.call(Legend.legendFn);
}
}
@@ -0,0 +1,388 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class ChartTimeline extends Chart implements Renderable {
private laneNames:string[];
private laneData:any[][];
private lanes:any;
private itemData:any;
private mainView:any;
private miniView:any;
private brush:any;
private x:any;
private x1:any;
private xTimeAxis:any;
private y1:any;
private y2:any;
private itemRects:any;
private rect:any;
private static MINI_LANE_HEIGHT_PX = 12;
private static ENTRY_LANE_HEIGHT_OFFSET_FRACTION:number = 0.05;
private static ENTRY_LANE_HEIGHT_TOTAL_FRACTION:number = 0.90;
private static MILLISEC_PER_MINUTE:number = 60 * 1000;
private static MILLISEC_PER_HOUR:number = 60 * ChartTimeline.MILLISEC_PER_MINUTE;
private static MILLISEC_PER_DAY:number = 24 * ChartTimeline.MILLISEC_PER_HOUR;
private static MILLISEC_PER_WEEK:number = 7 * ChartTimeline.MILLISEC_PER_DAY;
private static DEFAULT_COLOR = "LightGrey";
constructor(jsonStr:string) {
super(ComponentType.ChartTimeline, jsonStr);
var json = JSON.parse(jsonStr);
if (!json["componentType"]) json = json[ComponentType[ComponentType.ChartTimeline]];
this.laneNames = json['laneNames'];
this.laneData = json['laneData'];
}
render = (appendToObject:JQuery) => {
var instance = this;
var s:StyleChart = this.getStyle();
var margin:Margin = Style.getMargins(s);
//Format data
this.itemData = [];
var count = 0;
for (var i = 0; i < this.laneData.length; i++) {
for (var j = 0; j < this.laneData[i].length; j++) {
var obj = {};
obj["start"] = this.laneData[i][j]["startTimeMs"];
obj["end"] = this.laneData[i][j]["endTimeMs"];
obj["id"] = count++;
obj["lane"] = i;
obj["color"] = this.laneData[i][j]["color"];
obj["label"] = this.laneData[i][j]["entryLabel"];
this.itemData.push(obj);
}
}
this.lanes = [];
for (var i = 0; i < this.laneNames.length; i++) {
var obj = {};
obj["label"] = this.laneNames[i];
obj["id"] = i;
this.lanes.push(obj);
}
// Adds the svg canvas
//TODO don't hardcode these colors/attributes...
var svg = d3.select("#" + appendToObject.attr("id"))
.append("svg")
.style("stroke-width", ( s && s.getStrokeWidth() ? s.getStrokeWidth() : ChartConstants.DEFAULT_CHART_STROKE_WIDTH))
.style("fill", "none")
.attr("width", s.getWidth())
.attr("height", s.getHeight())
.append("g");
var heightExMargins = s.getHeight() - margin.top - margin.bottom;
var widthExMargins = s.getWidth() - margin.left - margin.right;
var miniHeight = this.laneNames.length * ChartTimeline.MINI_LANE_HEIGHT_PX;
var mainHeight = s.getHeight() - miniHeight - margin.top - margin.bottom - 25;
var minTime:number = d3.min(this.itemData, function (d:any) { return d.start; });
var maxTime:number = d3.max(this.itemData, function (d:any) { return d.end; });
this.x = d3.time.scale()
.domain([minTime, maxTime])
.range([0, widthExMargins]);
this.x1 = d3.time.scale().range([0, widthExMargins]);
this.y1 = d3.scale.linear().domain([0, this.laneNames.length]).range([0, mainHeight]);
this.y2 = d3.scale.linear().domain([0, this.laneNames.length]).range([0, miniHeight]);
//Add a rectangle for clipping the elements in each swimlane
this.rect = svg.append('defs').append('clipPath')
.attr('id', 'clip')
.append('rect')
.attr('width', widthExMargins)
.attr('height', s.getHeight() - 100);
this.mainView = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
.attr('width', widthExMargins)
.attr('height', mainHeight)
.attr('font-size', '12px')
.attr('font', 'sans-serif');
this.miniView = svg.append('g')
.attr('transform', 'translate(' + margin.left + ',' + (mainHeight + margin.top + 25) + ')') //25 being space for ticks/time label
.attr('width', widthExMargins)
.attr('height', miniHeight)
.attr('font-size', '10px')
.attr('font', 'sans-serif');
// Horizontal lane divider lines for mainView chart:
this.mainView.append('g').selectAll('.laneLines')
.data(this.lanes)
.enter().append('line')
.attr('x1', 0)
.attr('y1', function (d:any) {
return d3.round(instance.y1(d.id)) + 0.5;
})
.attr('x2', widthExMargins)
.attr('y2', function (d:any) {
return d3.round(instance.y1(d.id)) + 0.5;
})
.attr('stroke', 'lightgray')
.attr('stroke-width', 1);
//Add labels for lane text
this.mainView.append('g').selectAll('.laneText')
.data(this.lanes)
.enter().append('text')
.text(function (d:any) {
if(d.label) return d.label;
return "";
})
.attr('x', -10)
.attr('y', function (d:any) {
return instance.y1(d.id + .5);
})
.attr('text-anchor', 'end')
.attr("font","8pt sans-serif")
.attr('fill', 'black');
// Divider lines for miniView chart
this.miniView.append('g').selectAll('.laneLines')
.data(this.lanes)
.enter().append('line')
.attr('x1', 0)
.attr('y1', function (d:any) { return d3.round(instance.y2(d.id)) + 0.5; })
.attr('x2', widthExMargins)
.attr('y2', function (d:any) { return d3.round(instance.y2(d.id)) + 0.5; })
.attr('stroke', 'gray')
.attr('stroke-width', 1.0);
//Text for mini view
this.miniView.append('g').selectAll('.laneText')
.data(this.lanes)
.enter().append('text')
.text(function (d:any) {
if(d.label) return d.label;
return "";
})
.attr('x', -10)
.attr('y', function (d:any) {
return instance.y2(d.id + .5);
})
.attr('dy', '0.5ex')
.attr('text-anchor', 'end')
.attr('fill', 'black');
// Render time axis
this.xTimeAxis = d3.svg.axis()
.scale(this.x1)
.orient('bottom')
.ticks(d3.time.days, 1)
.tickFormat(d3.time.format('%a %d'))
.tickSize(6, 0);
//Time axis
var temp:any = this.mainView.append('g')
.attr('transform', 'translate(0,' + mainHeight + ')')
// .attr('class', 'mainView axis time')
.attr('class', 'timeAxis')
.attr('fill', 'black')
.style("stroke", "black").style("stroke-width", 1.0).style("fill", "black")
.attr("font", "10px sans-serif")
.call(this.xTimeAxis);
temp.selectAll('text').style("stroke-width", 0.0).attr('stroke-width', 0.0);
// draw the itemData
this.itemRects = this.mainView.append('g')
.attr('clip-path', 'url(#clip)');
//Entries for miniView chart
this.miniView.append('g').selectAll('miniItems')
.data(this.getMiniViewPaths(this.itemData))
.enter().append('path')
.attr('class', function (d:any) {
return 'miniItem ' + d.class;
})
.attr('d', function (d:any) {
return d.path;
})
.attr('stroke', 'black')
.attr('stroke-width', 'black');
// Draw the brush selection area (default - set extent to all data)
this.miniView.append('rect')
.attr('pointer-events', 'painted')
.attr('width', widthExMargins)
.attr('height', miniHeight)
.attr('visibility', 'hidden')
.on('mouseup', this.moveBrush);
this.brush = d3.svg.brush()
.x(this.x)
.extent([minTime, maxTime])
.on("brush", this.renderChart);
this.miniView.append('g')
.attr('class', 'x brush')
.call(this.brush)
.selectAll('rect')
.attr('y', 1)
.attr('height', miniHeight - 1)
.style('fill','gray')
.style('fill-opacity','0.2')
.style('stroke','DarkSlateGray')
.style('stroke-width',1);
this.miniView.selectAll('rect.background').remove();
this.renderChart();
//Add title (if present)
if (this.title) {
var titleStyle:StyleText;
if (this.style) titleStyle = this.style.getTitleStyle();
var text = svg.append("text")
.text(this.title)
.attr("x", (s.getWidth() / 2))
.attr("y", ((margin.top - 30) / 2))
.attr("text-anchor", "middle");
if (titleStyle) {
if (titleStyle.getFont()) text.attr("font-family", titleStyle.getFont);
if (titleStyle.getFontSize() != null) text.attr("font-size", titleStyle.getFontSize() + "pt");
if (titleStyle.getUnderline() != null) text.style("text-decoration", "underline");
if (titleStyle.getColor()) text.style("fill", titleStyle.getColor);
else text.style("fill", ChartConstants.DEFAULT_TITLE_COLOR);
} else {
text.style("text-decoration", "underline");
text.style("fill", ChartConstants.DEFAULT_TITLE_COLOR);
}
}
};
renderChart = () => {
var instance:any = this;
var extent:number[] = this.brush.extent();
var minExtent:number = extent[0];
var maxExtent:number = extent[1];
var visibleItems:any = this.itemData.filter(function (d) {
return d.start < maxExtent && d.end > minExtent
});
this.miniView.select('.brush').call(this.brush.extent([minExtent, maxExtent]));
this.x1.domain([minExtent, maxExtent]);
//https://github.com/d3/d3-time-format#timeFormat
var range = maxExtent - minExtent;
if (range > 2 * ChartTimeline.MILLISEC_PER_WEEK) {
this.xTimeAxis.ticks(d3.time.mondays, 1).tickFormat(d3.time.format('%a %d'));
} else if (range > 2 * ChartTimeline.MILLISEC_PER_DAY) {
this.xTimeAxis.ticks(d3.time.days, 1).tickFormat(d3.time.format('%a %d'));
} else if (range > 2 * ChartTimeline.MILLISEC_PER_HOUR) {
this.xTimeAxis.ticks(d3.time.hours, 4).tickFormat(d3.time.format('%H %p'));
} else if (range > 2 * ChartTimeline.MILLISEC_PER_MINUTE) {
this.xTimeAxis.ticks(d3.time.minutes, 1).tickFormat(d3.time.format('%H:%M'));
} else if (range >= 30000) {
this.xTimeAxis.ticks(d3.time.seconds, 10).tickFormat(d3.time.format('%H:%M:%S'));
} else {
this.xTimeAxis.ticks(d3.time.seconds, 1).tickFormat(d3.time.format('%H:%M:%S'));
} //no d3.time.milliseconds, so ticks below 1 second are not possible? (or, at least not using same approach as here)
// Update the axis
this.mainView.select('.timeAxis').call(this.xTimeAxis);
// Update the rectangles
var rects:any = this.itemRects.selectAll('rect')
.data(visibleItems, function (d) { return d.id; })
.attr('x', function (d) { return instance.x1(d.start); })
.attr('width', function (d) { return instance.x1(d.end) - instance.x1(d.start); });
//Set attributes for mainView swimlane rectangles
rects.enter().append('rect')
.attr('x', function (d) { return instance.x1(d.start); })
.attr('y', function (d) { return instance.y1(d.lane) + ChartTimeline.ENTRY_LANE_HEIGHT_OFFSET_FRACTION * instance.y1(1) + 0.5; })
.attr('width', function (d) { return instance.x1(d.end) - instance.x1(d.start); })
.attr('height', function (d) { return ChartTimeline.ENTRY_LANE_HEIGHT_TOTAL_FRACTION * instance.y1(1); })
.attr('stroke', 'black')
.attr('fill', function(d){
if(d.color) return d.color;
return ChartTimeline.DEFAULT_COLOR;
})
.attr('stroke-width', 1);
rects.exit().remove();
// Update the item labels
var labels:any = this.itemRects.selectAll('text')
.data(visibleItems, function (d) {
return d.id;
})
.attr('x', function (d) {
return instance.x1(Math.max(d.start, minExtent)) + 2;
})
.attr('fill', 'black');
labels.enter().append('text')
.text(function (d) {
if(instance.x1(d.end) - instance.x1(d.start) <= 30) return "";
if(d.label) return d.label;
return "";
})
.attr('x', function (d) {
return instance.x1(Math.max(d.start, minExtent)) + 2;
})
.attr('y', function (d) {
return instance.y1(d.lane) + .4 * instance.y1(1) + 0.5;
})
.attr('text-anchor', 'start')
.attr('class', 'itemLabel')
.attr('fill', 'black');
labels.exit().remove();
};
moveBrush = () => {
var origin:any = d3.mouse(this.rect[0]);
var time: any = this.x.invert(origin[0]).getTime();
var halfExtent: number = (this.brush.extent()[1].getTime() - this.brush.extent()[0].getTime()) / 2;
this.brush.extent([new Date(time - halfExtent), new Date(time + halfExtent)]);
this.renderChart();
};
getMiniViewPaths = (items:any) => {
var paths = {}, d, offset = .5 * this.y2(1) + 0.5, result = [];
for (var i = 0; i < items.length; i++) {
d = items[i];
if (!paths[d.class]) paths[d.class] = '';
paths[d.class] += ['M', this.x(d.start), (this.y2(d.lane) + offset), 'H', this.x(d.end)].join(' ');
}
for (var className in paths) {
result.push({class: className, path: paths[className]});
}
return result;
}
}
@@ -0,0 +1,86 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class Legend {
//TODO: make these configurable...
private static offsetX: number = 15;
private static offsetY: number = 15;
private static padding: number = 8;
private static separation: number = 12;
private static boxSize: number = 10;
private static fillColor: string = "#FFFFFF";
private static legendOpacity: number = 0.75;
private static borderStrokeColor: string = "#000000";
static legendFn = (function(g: any) {
//Get SVG and legend box/items:
var svg = d3.select(g.property("nearestViewportElement"));
var legendBox = g.selectAll(".outerRect").data([true]);
var legendItems = g.selectAll(".legendElement").data([true]);
legendBox.enter().append("rect").attr("class","outerRect");
legendItems.enter().append("g").attr("class","legendElement");
var legendElements: any[] = [];
svg.selectAll("[data-legend]").each(function() {
var thisVar = d3.select(this);
legendElements.push({
label: thisVar.attr("data-legend"),
color: thisVar.style("fill")
});
});
//Add rectangles for color
legendItems.selectAll("rect")
.data(legendElements,function(d) { return d.label})
.call(function(d) { d.enter().append("rect")})
.call(function(d) { d.exit().remove()})
.attr("x",0)
.attr("y",function(d,i) { return i*Legend.separation-Legend.boxSize+"px"})
.attr("width",Legend.boxSize)
.attr("height",Legend.boxSize)
//.style("fill",function(d) { return d.value.color});
.style("fill",function(d) { return d.color});
//Add labels
legendItems.selectAll("text")
.data(legendElements,function(d) { return d.label})
.call(function(d) { d.enter().append("text")})
.call(function(d) { d.exit().remove()})
.attr("y",function(d,i) { return i*Legend.separation + "px"})
.attr("x",(Legend.padding + Legend.boxSize) + "px")
.text(function(d) { return d.label});
//Add the outer box
var legendBoundingBox: any = legendItems[0][0].getBBox();
legendBox.attr("x",(legendBoundingBox.x-Legend.padding))
.attr("y",(legendBoundingBox.y-Legend.padding))
.attr("height",(legendBoundingBox.height+2*Legend.padding))
.attr("width",(legendBoundingBox.width+2*Legend.padding))
.style("fill",Legend.fillColor)
.style("stroke",Legend.borderStrokeColor)
.style("opacity",Legend.legendOpacity);
svg.selectAll(".legend").attr("transform","translate(" + Legend.offsetX + "," + Legend.offsetY + ")");
});
}
@@ -0,0 +1,53 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class StyleChart extends Style {
protected strokeWidth: number;
protected pointSize: number;
protected seriesColors: string[];
protected axisStrokeWidth: number;
protected titleStyle: StyleText;
constructor( jsonObj: any ){
super(jsonObj['StyleChart']);
var style: any = jsonObj['StyleChart'];
if(style){
this.strokeWidth = style['strokeWidth'];
this.pointSize = style['pointSize'];
this.seriesColors = style['seriesColors'];
if(style['titleStyle']) this.titleStyle = new StyleText(style['titleStyle']);
}
}
getStrokeWidth = () => this.strokeWidth;
getPointSize = () => this.pointSize;
getSeriesColors = () => this.seriesColors;
getSeriesColor = (idx: number) => {
if(!this.seriesColors || idx < 0 || idx > this.seriesColors.length) return null;
return this.seriesColors[idx];
};
getAxisStrokeWidth = () => this.axisStrokeWidth;
getTitleStyle = () => this.titleStyle;
}
@@ -0,0 +1,77 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class ComponentDiv extends Component implements Renderable {
private style: StyleDiv;
private components: Renderable[];
constructor(jsonStr: string){
super(ComponentType.ComponentDiv);
var json = JSON.parse(jsonStr);
if(!json["componentType"]) json = json[ComponentType[ComponentType.ComponentDiv]];
var components: any[] = json['components'];
if(components){
this.components = [];
for( var i=0; i<components.length; i++ ){
var asStr: string = JSON.stringify(components[i]);
this.components.push(Component.getComponent(asStr));
}
}
if(json['style']) this.style = new StyleDiv(json['style']);
}
render = (appendToObject: JQuery) => {
var newDiv: JQuery = $('<div></div>');
newDiv.uniqueId();
if(this.style){
if(this.style.getWidth()){
var unit: string = this.style.getWidthUnit();
newDiv.width(this.style.getWidth() + (unit ? unit : ""));
}
if(this.style.getHeight()){
var unit: string = this.style.getHeightUnit();
newDiv.height(this.style.getHeight() + (unit ? unit : ""));
}
if(this.style.getBackgroundColor()) newDiv.css("background-color",this.style.getBackgroundColor());
if(this.style.getFloatValue()) newDiv.css("float", this.style.getFloatValue());
}
//Adding the div before adding the sub-components seems to be important for charts/d3 to work properly
appendToObject.append(newDiv);
//now, add the sub-components:
if(this.components){
for( var i=0; i<this.components.length; i++ ){
this.components[i].render(newDiv);
}
}
}
}
@@ -0,0 +1,35 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class StyleDiv extends Style {
protected floatValue: string;
constructor( jsonObj: any){
super(jsonObj['StyleDiv']);
if(jsonObj && jsonObj['StyleDiv']) this.floatValue = jsonObj['StyleDiv']['floatValue'];
}
getFloatValue = () => this.floatValue;
}
@@ -0,0 +1,90 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class DecoratorAccordion extends Component implements Renderable {
private style: StyleAccordion;
private title: string;
private defaultCollapsed: boolean;
private innerComponents: Renderable[];
constructor(jsonStr: string){
super(ComponentType.DecoratorAccordion);
var json = JSON.parse(jsonStr);
if(!json["componentType"]) json = json[ComponentType[ComponentType.DecoratorAccordion]];
this.title = json['title'];
this.defaultCollapsed = json['defaultCollapsed'];
var innerCs: any[] = json['innerComponents'];
if(innerCs){
this.innerComponents = [];
for( var i=0; i<innerCs.length; i++ ){
var asStr: string = JSON.stringify(innerCs[i]);
this.innerComponents.push(Component.getComponent(asStr));
}
}
if(json['style']) this.style = new StyleAccordion(json['style']);
}
render = (appendToObject: JQuery) => {
var s:StyleAccordion = this.style;
var outerDiv: JQuery = $('<div></div>');
outerDiv.uniqueId();
var titleDiv: JQuery;
if(this.title) titleDiv = $('<div>' + this.title + '</div>');
else titleDiv = $('<div></div>');
titleDiv.uniqueId();
outerDiv.append(titleDiv);
var innerDiv: JQuery = $('<div></div>');
innerDiv.uniqueId();
outerDiv.append(innerDiv);
//Add the inner components:
if (this.innerComponents) {
for (var i = 0; i < this.innerComponents.length; i++) {
//this.innerComponents[i].render(outerDiv);
this.innerComponents[i].render(innerDiv);
}
}
appendToObject.append(outerDiv);
if(this.defaultCollapsed) outerDiv.accordion({collapsible: true, heightStyle: "content", active: false});
else outerDiv.accordion({collapsible: true, heightStyle: "content"});
//$(function(){outerDiv.accordion({collapsible: true, heightStyle: "content"})});
//elementdiv.accordion();
//$(function(){elementdiv.accordion()});
}
}
@@ -0,0 +1,29 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class StyleAccordion extends Style {
constructor( jsonObj: any){
super(jsonObj['StyleAccordion']);
}
}
@@ -0,0 +1,106 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class ComponentTable extends Component implements Renderable {
private header: string[];
private content: string[][];
private style: StyleTable;
constructor(jsonStr: string){
super(ComponentType.ComponentTable);
var json = JSON.parse(jsonStr);
if(!json["componentType"]) json = json[ComponentType[ComponentType.ComponentTable]];
this.header = json['header'];
this.content = json['content'];
if(json['style']) this.style = new StyleTable(json['style']);
}
render = (appendToObject: JQuery) => {
var s: StyleTable = this.style;
var margin: Margin = Style.getMargins(s);
var tbl = document.createElement('table');
//TODO allow setting of table width/height
tbl.style.width = '100%';
if(s && s.getBorderWidthPx() != null ) tbl.setAttribute('border', String(s.getBorderWidthPx()));
if(s && s.getBackgroundColor()) tbl.style.backgroundColor = s.getBackgroundColor();
if(s && s.getWhitespaceMode()) tbl.style.whiteSpace = s.getWhitespaceMode();
if (s && s.getColumnWidths()) {
//TODO allow other than percentage
var colWidths: number[] = s.getColumnWidths();
var unit: string = TSUtils.normalizeLengthUnit(s.getColumnWidthUnit());
for (var i = 0; i < colWidths.length; i++) {
var col = document.createElement('col');
col.setAttribute('width', colWidths[i] + unit);
tbl.appendChild(col);
}
}
//TODO: don't hardcode
var padTop = 1;
var padRight = 1;
var padBottom = 1;
var padLeft = 1;
if (this.header) {
var theader = document.createElement('thead');
var headerRow = document.createElement('tr');
if(s && s.getHeaderColor()) headerRow.style.backgroundColor = s.getHeaderColor();
for (var i = 0; i < this.header.length; i++) {
var headerd = document.createElement('th');
headerd.style.padding = padTop + 'px ' + padRight + 'px ' + padBottom + 'px ' + padLeft + 'px';
headerd.appendChild(document.createTextNode(this.header[i]));
headerRow.appendChild(headerd);
}
tbl.appendChild(headerRow);
}
//Add content:
if (this.content) {
var tbdy = document.createElement('tbody');
for (var i = 0; i < this.content.length; i++) {
var tr = document.createElement('tr');
for (var j = 0; j < this.content[i].length; j++) {
var td = document.createElement('td');
td.style.padding = padTop + 'px ' + padRight + 'px ' + padBottom + 'px ' + padLeft + 'px';
td.appendChild(document.createTextNode(this.content[i][j]));
tr.appendChild(td);
}
tbdy.appendChild(tr);
}
tbl.appendChild(tbdy);
}
appendToObject.append(tbl);
}
}
@@ -0,0 +1,47 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class StyleTable extends Style {
private columnWidths: number[];
private columnWidthUnit: string;
private borderWidthPx: number;
private headerColor: string;
private whitespaceMode: string;
constructor( jsonObj: any ){
super(jsonObj['StyleTable']);
var style: any = jsonObj['StyleTable'];
if(style){
this.columnWidths = jsonObj['StyleTable']['columnWidths'];
this.borderWidthPx = jsonObj['StyleTable']['borderWidthPx'];
this.headerColor = jsonObj['StyleTable']['headerColor'];
this.columnWidthUnit = jsonObj['StyleTable']['columnWidthUnit'];
this.whitespaceMode = jsonObj['StyleTable']['whitespaceMode'];
}
}
getColumnWidths = () => this.columnWidths;
getColumnWidthUnit = () => this.columnWidthUnit;
getBorderWidthPx = () => this.borderWidthPx;
getHeaderColor = () => this.headerColor;
getWhitespaceMode = () => this.whitespaceMode;
}
@@ -0,0 +1,61 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class ComponentText extends Component implements Renderable {
private text: string;
private style: StyleText;
constructor(jsonStr: string){
super(ComponentType.ComponentText);
var json = JSON.parse(jsonStr);
if(!json["componentType"]) json = json[ComponentType[ComponentType.ComponentText]];
this.text = json['text'];
if(json['style']) this.style = new StyleText(json['style']);
}
render = (appendToObject: JQuery) => {
var textNode: Text = document.createTextNode(this.text);
if(this.style){
var newSpan: HTMLSpanElement = document.createElement('span');
if(this.style.getFont()) newSpan.style.font = this.style.getFont();
if(this.style.getFontSize() != null) newSpan.style.fontSize = this.style.getFontSize() + "pt";
if(this.style.getUnderline() != null) newSpan.style.textDecoration='underline';
if(this.style.getColor()) newSpan.style.color = this.style.getColor();
if(this.style.getMarginTop()) newSpan.style.marginTop = this.style.getMarginTop() + "px";
if(this.style.getMarginBottom()) newSpan.style.marginBottom = this.style.getMarginBottom() + "px";
if(this.style.getMarginLeft()) newSpan.style.marginLeft = this.style.getMarginLeft() + "px";
if(this.style.getMarginRight()) newSpan.style.marginRight = this.style.getMarginRight() + "px";
if(this.style.getWhitespacePre()) newSpan.style.whiteSpace = 'pre';
newSpan.appendChild(textNode);
appendToObject.append(newSpan);
} else {
var newSpan: HTMLSpanElement = document.createElement('span');
//appendToObject.append(textNode);
newSpan.appendChild(textNode);
appendToObject.append(newSpan);
}
}
}
@@ -0,0 +1,47 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class StyleText extends Style {
private font: string;
private fontSize: number;
private underline: boolean;
private color: string;
private whitespacePre: boolean;
constructor( jsonObj: any){
super(jsonObj['StyleText']);
var style: any = jsonObj['StyleText'];
if(style){
this.font = style['font'];
this.fontSize = style['fontSize'];
this.underline = style['underline'];
this.color = style['color'];
this.whitespacePre = style['whitespacePre'];
}
}
getFont = () => this.font;
getFontSize = () => this.fontSize;
getUnderline = () => this.underline;
getColor = () => this.color;
getWhitespacePre = () => this.whitespacePre;
}
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"outFile": "../../../../resources/assets/dl4j-ui.js",
"removeComments": true,
"sourceMap": true,
"declaration": true
},
"filesGlob": [
"**/*.ts"
]
}
@@ -0,0 +1,66 @@
/*
* ******************************************************************************
* *
* *
* * This program and the accompanying materials are made available under the
* * terms of the Apache License, Version 2.0 which is available at
* * https://www.apache.org/licenses/LICENSE-2.0.
* *
* * See the NOTICE file distributed with this work for additional
* * information regarding copyright ownership.
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* * License for the specific language governing permissions and limitations
* * under the License.
* *
* * SPDX-License-Identifier: Apache-2.0
* *****************************************************************************
*/
class TSUtils {
//Get the maximum value
static max(input: number[][]): number {
var max: number = -Number.MAX_VALUE;
for (var i = 0; i < input.length; i++) {
for( var j=0; j<input[i].length; j++ ){
max = Math.max(max,input[i][j]);
}
}
return max;
}
//Get the minimum value
static min(input: number[][]): number {
var min: number = Number.MAX_VALUE;
for (var i = 0; i < input.length; i++) {
for( var j=0; j<input[i].length; j++ ){
min = Math.min(min,input[i][j]);
}
}
return min;
}
//Normalize the length unit (for example, parse the LengthUnit enum values)
static normalizeLengthUnit(input: string): string{
if(input == null) return input;
switch(input.toLowerCase()){
case "px":
return "px";
case "percent":
case "%":
return "%";
case "cm":
return "cm";
case "mm":
return "mm";
case "in":
return "in";
default:
return input;
}
}
}