blob: 382fa4c09ed0dfc619839b996a6b0fde07df6317 [file] [log] [blame]
/*********************************************************************************
* Copyright (c) 2020 Robert Bosch GmbH and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Robert Bosch GmbH - initial API and implementation
********************************************************************************
*/
package org.eclipse.app4mc.amalthea.visualizations.standard;
import javax.annotation.PostConstruct;
import org.eclipse.app4mc.amalthea.model.Runnable;
import org.eclipse.app4mc.amalthea.visualizations.standard.util.RunnableHelper;
import org.eclipse.app4mc.amalthea.visualizations.standard.util.RunnablePainter;
import org.eclipse.app4mc.visualization.ui.registry.Visualization;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.osgi.service.component.annotations.Component;
import javafx.embed.swt.FXCanvas;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
@Component(property= {
"name=LabelAccess View",
"description=Graphical representation of Runnable LabelAccess definition"
})
public class RunnableVisualization implements Visualization {
@PostConstruct
public void createVisualization(Runnable runnable, Composite parent) {
parent.setLayout(new GridLayout());
FXCanvas fxCanvas = new FXCanvas(parent, SWT.NONE);
GridDataFactory
.fillDefaults()
.grab(true, true)
.applyTo(fxCanvas);
// create the root layout pane
BorderPane layout = new BorderPane();
layout.setBackground(new Background(new BackgroundFill(Color.WHITE, null, null)));
// create a Scene instance
// set the layout container as root
// set the background fill to the background color of the shell
Scene scene = new Scene(layout);
// set the Scene to the FXCanvas
fxCanvas.setScene(scene);
RunnablePainter painter = new RunnablePainter(runnable);
// calculate the max scale factor
double minWidth = painter.getPreferredMinimumWidth();
double minHeight = painter.getPreferredMinimumHeight();
double max = Math.max(minWidth, minHeight);
double factor = RunnableHelper.CANVAS_MAX / max;
painter.setMaxScaleFactor(factor);
// add zoom buttons
Button zoomIn = new Button("+");
zoomIn.setPrefSize(40, 40);
Button zoomOut = new Button("-");
zoomOut.setPrefSize(40, 40);
zoomIn.setOnAction(event -> {
if (!zoomIn.isDisabled()) {
painter.zoomIn();
if (painter.getScaleFactor() == painter.getMaxScaleFactor()) {
zoomIn.setDisable(true);
}
if (zoomOut.isDisabled()) {
zoomOut.setDisable(false);
}
}
parent.redraw();
});
zoomOut.setOnAction(event -> {
if (!zoomOut.isDisabled()) {
painter.zoomOut();
if (painter.getScaleFactor() == 0.1) {
zoomOut.setDisable(true);
}
if (zoomIn.isDisabled()) {
zoomIn.setDisable(false);
}
}
parent.redraw();
});
VBox vBox = new VBox(5);
vBox.setPadding(new Insets(5));
vBox.getChildren().addAll(zoomIn, zoomOut);
layout.setLeft(vBox);
// disable zoom buttons if max scaling is reached on start
if (painter.getScaleFactor() == painter.getMaxScaleFactor()) {
zoomIn.setDisable(true);
}
if (painter.getScaleFactor() == 0.1) {
zoomOut.setDisable(true);
}
Canvas canvas = new Canvas();
ScrollPane scrollable = new ScrollPane();
scrollable.setPadding(new Insets(0));
scrollable.setStyle("-fx-background: rgb(255,255,255);\n -fx-background-color: rgb(255,255,255)");
scrollable.setContent(canvas);
layout.setCenter(scrollable);
canvas.setOnScroll(event -> {
if (event.isControlDown()) {
double deltaY = event.getDeltaY();
if (deltaY < 0){
zoomOut.fire();
} else {
zoomIn.fire();
}
event.consume();
}
});
GraphicsContext gc = canvas.getGraphicsContext2D();
parent.addPaintListener(e -> {
org.eclipse.swt.graphics.Rectangle parentBounds = parent.getBounds();
double scaledColumnWidth = painter.getPreferredMinimumWidth() * painter.getScaleFactor();
double scaledRowHeight = painter.getPreferredMinimumHeight() * painter.getScaleFactor();
double canvasWidth = scaledColumnWidth;
double canvasHeight = scaledRowHeight;
double parentBoundsWidth = parentBounds.width - 30d - vBox.getWidth();
if (parentBoundsWidth > scaledColumnWidth) {
canvasWidth = parentBoundsWidth;
}
double parentBoundsHeight = parentBounds.height - 30d;
if (parentBoundsHeight > scaledRowHeight) {
canvasHeight = parentBoundsHeight;
}
// textures with bigger dimensions than 8192 x 8192 can't processed by even modern graphic cards
// therefore we max it out by applying the max zoom factor we set to the painter before
canvasWidth = Math.min(RunnableHelper.CANVAS_MAX, canvasWidth);
canvasHeight = Math.min(RunnableHelper.CANVAS_MAX, canvasHeight);
canvas.setWidth(canvasWidth);
canvas.setHeight(canvasHeight);
gc.clearRect(0, 0, canvasWidth, canvasHeight);
Rectangle bounds = new Rectangle(
Double.valueOf(parentBounds.x),
Double.valueOf(parentBounds.y),
Double.valueOf(scaledColumnWidth),
Double.valueOf(scaledRowHeight));
painter.paint(gc, bounds);
});
}
}