| /********************************************************************************* |
| * 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); |
| }); |
| } |
| } |