ge-high-assurance / RITE

DARPA's Automated Rapid Certification of Software (ARCOS) project called RITE (RACK Integrated CerTification Environment)
BSD 3-Clause "New" or "Revised" License
3 stars 1 forks source link

Integrate JavaFX Views into Eclipse Views #139

Open pauls4GE opened 11 months ago

pauls4GE commented 11 months ago

Can the Javafx windows be made to look more integrated into the Eclipse environment?

Resources: https://wiki.eclipse.org/Efxclipse/Tutorials/Tutorial2

baoluomeng commented 11 months ago

You may need to install a special set of plugins for your Eclipse dev env for JavaFX apps: https://marketplace.eclipse.org/content/efxclipse

baoluomeng commented 11 months ago

Below is the code that can integrate JavaFX views with Eclipse views. You will need to make sure all the javafx packages are imported into the project. I tested the code using Zulu-17.0.8.fx , which bundles Java 17 and JavaFx.

package fx8.views;

import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;

import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;

import java.awt.Frame;

import javax.swing.JPanel;

import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;

public class MyViewPart extends ViewPart {
    @Override
    public void createPartControl(final Composite parent) {
        Composite composite = new Composite(parent, SWT.EMBEDDED
                | SWT.NO_BACKGROUND);
        final Frame frame = SWT_AWT.new_Frame(composite);

        final JPanel parentPanel = new JPanel();

        final JFXPanel fxPanel = new JFXPanel();

        final TabPane tPane = new TabPane();
        Tab firstTab = new Tab("First Tab");

        GridPane gPane = new GridPane();
        gPane.setHgap(10.0);
        gPane.setVgap(10.0);

        final TextField tField = new TextField();
        tField.setPrefWidth(100.0);
        tField.setEditable(true);
        tField.managedProperty().bind(tField.editableProperty());
        tField.setStyle("-fx-border-color: black; -fx-border-width: 2");

        Label userName = new Label("User Name");

        gPane.add(userName, 0, 0);
        gPane.add(tField, 1, 0);

        firstTab.setContent(gPane);
        tPane.getTabs().add(firstTab);

        Platform.runLater(new Runnable() {

            @Override
            public void run() {
                Scene scene = new Scene(tPane);
                fxPanel.setScene(scene);

                parentPanel.add(fxPanel);
                frame.add(parentPanel);
                frame.setSize(1300, 600);
                frame.setVisible(true);
            }
        });
    }

    @Override
    public void setFocus() {
        // what do we need to do here?
    }

}
baoluomeng commented 11 months ago

Screenshot 2023-10-10 at 1 20 24 PM

baoluomeng commented 11 months ago

Below is the plugin.xml file

<?eclipse version="3.4"?>
<plugin>

   <extension
         point="org.eclipse.ui.views">
      <view
            id="fx8.views.MyViewPart"
            name="My FX View"
            class="fx8.views.MyViewPart">
      </view>
   </extension>

</plugin>
baoluomeng commented 11 months ago

The goal is to embed the reporting feature as an Eclipse view. There are people recommending using FXCanvas instead of JFXPanel to embed Javafx view into Eclipse. I am not sure which one is better. Haven't tried FXCanvas yet. FXCanvas is from the javafx.swt.jar, which is part of JavaFX distributions.

https://docs.oracle.com/javafx/2/swt_interoperability/jfxpub-swt_interoperability.htm

baoluomeng commented 11 months ago

Here is an example using FXCanvas to connect JavaFX with SWT (eclipse view): https://www.javatips.net/api/EclipseDay-Presentation-master/org.eclipseday.javafx.rcpdemo/src/org/eclipseday/javafx/rcpdemo/view/EffectView.java

pauls4GE commented 10 months ago

@davidcok do not add to https://github.com/ge-high-assurance/RITE/tree/dev

baoluomeng commented 9 months ago

Here is another example using FXCanvas inside Eclipse.


import java.text.DecimalFormat;
import java.text.NumberFormat;
import javafx.beans.property.DoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swt.FXCanvas;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.effect.Effect;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

/**
 * This sample class demonstrates how to integrate a workbench view which uses the JavaFX SDK to
 * draw the view.
 */
public class EffectView extends ViewPart {

    /** The ID of the view as specified by the extension. */
    public static final String ID = "traceplugin.views.Effect";

    private static final NumberFormat DECIMAL = new DecimalFormat("0.0");
    private static final String CUSTOM_CAR = "/resources/images/Custom_car.jpg";

    private FXCanvas canvas;
    private BorderPane rootNode;

    /** This is a callback that will allow us to create the view and initialize it. */
    @Override
    public void createPartControl(final Composite parent) {
        this.canvas = new FXCanvas(parent, SWT.NONE);
        this.rootNode = new BorderPane();

        final Scene scene = new Scene(this.rootNode, 800, 600, Color.WHITE);
        this.canvas.setScene(scene);

        final ColorAdjust fx = new ColorAdjust();
        fx.setHue(0.5);
        fx.setSaturation(0.4);
        fx.setBrightness(0.5);
        fx.setContrast(0.5);

        displayImage(CUSTOM_CAR, fx);

        displaySliders(
                buildSlider("Hue", fx.hueProperty(), -1.0, 1.0),
                buildSlider("Saturation", fx.saturationProperty(), -1.0, 1.0),
                buildSlider("Brightness", fx.brightnessProperty(), -1.0, 1.0),
                buildSlider("Contrast", fx.contrastProperty(), -1.0, 1.0));

        BorderPane.setAlignment(this.rootNode.getCenter(), Pos.CENTER);
    }

    /**
     * Draws the image.
     *
     * @param image Name of image file
     * @param fx Effector for adjusting colors
     */
    private void displayImage(final String image, final Effect fx) {
        final ImageView iv = new ImageView();
        iv.setEffect(fx);
        iv.setImage(new Image(this.getClass().getResourceAsStream(image)));
        BorderPane.setMargin(iv, new Insets(10));
        this.rootNode.setCenter(iv);
    }

    /**
     * Draws the sliders.
     *
     * @param sliders Sliders for adjusting colors
     */
    private void displaySliders(final Node... sliders) {
        FlowPane flow = new FlowPane(sliders);
        flow.setOrientation(Orientation.VERTICAL);
        flow.setAlignment(Pos.CENTER);
        this.rootNode.setRight(flow);
        BorderPane.setMargin(this.rootNode.getRight(), new Insets(10));
        BorderPane.setAlignment(this.rootNode.getRight(), Pos.CENTER);
        this.rootNode.getRight().setStyle("-fx-border-color:#000000;-fx-border-width:2px;");
    }

    /**
     * Builds a slider.
     *
     * @param name Name of slider
     * @param property Effector property to read
     * @param min Minimum endpoint of slider range
     * @param max Maximum endpoint of slider range
     */
    private HBox buildSlider(
            final String name, final DoubleProperty property, final double min, final double max) {

        final Slider slider = new Slider();
        slider.setMin(min);
        slider.setMax(max);
        slider.setMaxWidth(80);
        slider.setValue(property.doubleValue());
        slider.setBlockIncrement(0.1);

        slider.addEventFilter(
                MouseEvent.MOUSE_CLICKED,
                new EventHandler<MouseEvent>() {
                    @Override
                    public void handle(final MouseEvent event) {
                        event.consume();
                    }
                });

        slider.adjustValue(property.doubleValue());
        property.bind(slider.valueProperty());
        final Label valueLabel = new Label(name);

        slider.valueProperty()
                .addListener(
                        new ChangeListener<Number>() {
                            @Override
                            public void changed(
                                    final ObservableValue<? extends Number> observable,
                                    final Number oldValue,
                                    final Number newValue) {
                                valueLabel.setText(DECIMAL.format(newValue));
                            }
                        });

        final Label nameLabel = new Label(name);
        return new HBox(nameLabel, slider, valueLabel);
    }

    /** Passes the focus to the view's canvas. */
    @Override
    public void setFocus() {
        this.canvas.setFocus();
    }
}
baoluomeng commented 9 months ago

Below shows the effect view.

80313b27-6fdb-4264-8804-703f2dc1fc5a

baoluomeng commented 8 months ago

import java.awt.Frame;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javax.swing.JPanel;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import org.osgi.framework.Bundle;

public class ConflictReportView extends ViewPart {
    /** The ID of the view as specified by the extension. */
    public static final String ID = "com.ge.research.trace.gui.conflictReportView";

    /** This is a callback that will allow us to create the view and initialize it. */
    @Override
    public void createPartControl(final Composite parent) {
        Composite composite = new Composite(parent, SWT.EMBEDDED | SWT.NO_BACKGROUND);
        final Frame frame = SWT_AWT.new_Frame(composite);

        final JPanel parentPanel = new JPanel();

        final JFXPanel fxPanel = new JFXPanel();

        try {
            FXMLLoader loader = new FXMLLoader();
            final Bundle bundle = org.eclipse.core.runtime.Platform.getBundle("plugin");
            String fxmlFilePath = "resources/hello.fxml";
            final URL fxmlUrl =
                    FileLocator.toFileURL(FileLocator.find(bundle, new Path(fxmlFilePath), null));
            loader.setLocation(fxmlUrl);
            final VBox vbox = loader.<VBox>load();

            Platform.runLater(
                    new Runnable() {

                        @Override
                        public void run() {
                            Scene scene = new Scene(vbox);
                            fxPanel.setScene(scene);

                            parentPanel.add(fxPanel);
                            frame.add(parentPanel);
                            frame.setSize(1300, 600);
                            frame.setVisible(true);
                        }
                    });
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void setFocus() {}
}
baoluomeng commented 8 months ago

import java.awt.Frame;
import java.io.IOException;
import java.net.MalformedURLException;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javax.swing.JPanel;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;

public class ConflictReportView extends ViewPart {

    /** The ID of the view as specified by the extension. */
    public static final String ID = "com.ge.research.trace.gui.conflictReportView";

    /** This is a callback that will allow us to create the view and initialize it. */
    @Override
    public void createPartControl(final Composite parent) {
        Composite composite = new Composite(parent, SWT.EMBEDDED | SWT.NO_BACKGROUND);
        final Frame frame = SWT_AWT.new_Frame(composite);

        final JPanel parentPanel = new JPanel();

        final JFXPanel fxPanel = new JFXPanel();

        try {

            Parent sceneMain = FXMLLoader.load(getClass().getResource("/resources/hello.fxml"));
            Platform.setImplicitExit(false);
            Platform.runLater(
                    new Runnable() {

                        @Override
                        public void run() {
                            Scene scene = new Scene(sceneMain);
                            fxPanel.setScene(scene);

                            parentPanel.add(fxPanel);
                            frame.add(parentPanel);
                            frame.setSize(1300, 600);
                            frame.setVisible(true);
                        }
                    });
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /** Passes the focus to the view's canvas. */
    @Override
    public void setFocus() {}
}