diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/.ratings b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/.ratings index ecdbc89bc0c71ac7d43329f351e821b0bf31500c..33bacee5815095621863fb59305fcfe4a1f6c703 100644 --- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/.ratings +++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/.ratings @@ -1 +1 @@ -AF3FXViewPart.java 67cc6f943239c695bf2965502ccc05091f3dd346 GREEN +AF3FXViewPart.java 66e5e5d93b3e03cc2202c9213ee2636d40fb6833 YELLOW diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/AF3FXViewPart.java b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/AF3FXViewPart.java index 67cc6f943239c695bf2965502ccc05091f3dd346..66e5e5d93b3e03cc2202c9213ee2636d40fb6833 100644 --- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/AF3FXViewPart.java +++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/AF3FXViewPart.java @@ -15,108 +15,78 @@ +--------------------------------------------------------------------------*/ package org.fortiss.tooling.common.ui.javafx; -import static org.fortiss.tooling.common.ui.javafx.util.JavaFXUtils.loadFXML; +import static javafx.scene.layout.AnchorPane.setBottomAnchor; +import static javafx.scene.layout.AnchorPane.setLeftAnchor; +import static javafx.scene.layout.AnchorPane.setRightAnchor; +import static javafx.scene.layout.AnchorPane.setTopAnchor; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.net.URL; -import java.util.ResourceBundle; import org.apache.commons.lang3.SystemUtils; import org.eclipse.fx.ui.workbench3.FXViewPart; import org.fortiss.tooling.common.ui.javafx.layout.ICompositeFXController; import javafx.application.Platform; -import javafx.fxml.Initializable; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.Pane; /** - * Base class to create eclipse (SWT-based) views using JavaFX GUI elements. This class requires - * FXML file that defines the GUI elements of the view. + * Base class to create eclipse (SWT-based) views using JavaFX GUI elements. * - * @author diewald + * @author munaro */ -public abstract class AF3FXViewPart extends FXViewPart - implements ICompositeFXController, Initializable { +public abstract class AF3FXViewPart extends FXViewPart { + /** For later use, if we need to define different styles. */ private String cssLocation; /** Flag that indicates if a custom style sheet has been applied. */ private boolean isCustomStyleSheetApplied; - /** References the stub that defines the FXML file defining the layout and controller. */ - private Class<? extends AF3FXViewPart> viewerClass; - /** References the root {@link Pane} to which GUI elements must be added to be displayed. */ private Pane root; - /** {@link ICompositeFXController}s to be added to a container node within the view part. */ - private ICompositeFXController[] containments; + /** Specifies the view part's layout and logic. */ + private ICompositeFXController controller; /** - * Constructor. + * Constructor. Allows to pass the view's FXML definition file. * - * @param viewerClass - * Class implementing the {@link AF3FXViewPart} to load resources from its containing - * bundle. + * @param controller + * {@link ICompositeFXController} specifying the layout of the view part as well as + * its logic. * @param cssLocation * style sheet file path for the appearance settings relative to the source * (resource) folders. Pass {@code null} if the OS-native look shall be used. - * @param containments - * Optional {@link ICompositeFXController}s to be added to a container node within - * the view - * part. * @throws Exception * if the given FXML file path is not given or if it cannot be found in any of the * source (resource) folders. */ - public AF3FXViewPart(Class<? extends AF3FXViewPart> viewerClass, String cssLocation, - ICompositeFXController... containments) throws Exception { + public AF3FXViewPart(ICompositeFXController controller, String cssLocation) throws Exception { Platform.setImplicitExit(false); - this.viewerClass = viewerClass; this.cssLocation = cssLocation; - this.containments = containments; + this.controller = controller; } /** {@inheritDoc} */ @Override protected Scene createFxScene() { - if(getFXMLLocation() != null) { - URL fxmlResource = viewerClass.getResource(getFXMLLocation()); - try { - root = loadFXML(fxmlResource, this); - } catch(IOException e) { - throw new RuntimeException( - "Cannot load the resource located at " + getFXMLLocation(), e); - } - } else { - root = new AnchorPane(); - try { - viewerClass.getMethod("initialize", URL.class, ResourceBundle.class).invoke(this, - null, null); - } catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException | - SecurityException e) { - throw new RuntimeException("The initialize method of the View " + - viewerClass.getSimpleName() + " threw an exception!", e); - } catch(NoSuchMethodException e) { - throw new RuntimeException("For single Controller views, an initialize method is " + - "required that creates the control! This cannot be done in constructors " + - "since the JavaFX toolkit is not initialized in that stage.", e); - } - } + Node layout = controller.getOrLoadLayout(); + + setTopAnchor(layout, 0.0); + setRightAnchor(layout, 0.0); + setBottomAnchor(layout, 0.0); + setLeftAnchor(layout, 0.0); + root = new AnchorPane(layout); if(cssLocation != null) { isCustomStyleSheetApplied = applyStyleSheet(root, getClass(), cssLocation); } if(!isCustomStyleSheetApplied) { setNativeLook(root); } - - addContainments(containments); - Scene scene = new Scene(root); return scene; } @@ -127,36 +97,6 @@ public abstract class AF3FXViewPart extends FXViewPart // Not needed. } - /** - * Adds a single {@link Node} to this view. It embeds the given {@link Node} to the - * {@link AnchorPane} of this view and stretches it to the borders of the view. - * <p> - * NOTE: This method may only be used for single-control views, not FXML-based ones. - * - * @param fxNode - * {@link Node} to be added to the view. - */ - protected void setChildNodeFinal(Node fxNode) { - if(getFXMLLocation() != null) { - throw new RuntimeException("This method is intended for single-control views. It may" + - " not be used for FXML-based views."); - } - if(!root.getChildren().isEmpty()) { - throw new RuntimeException("The method setChildNodeFinal was invoked more than once." + - " This method is intended for single-control views. If more controls" + - "shall be added, please define an FXML layout file and call the appropriate" + - " constructors."); - } - - root.getChildren().add(fxNode); - // Stretch the node to the borders of the view. In the createScene method, we a create a - // root pane that is an AnchorPane, so we can safely use these calls here. - AnchorPane.setTopAnchor(fxNode, 0.0); - AnchorPane.setRightAnchor(fxNode, 0.0); - AnchorPane.setBottomAnchor(fxNode, 0.0); - AnchorPane.setLeftAnchor(fxNode, 0.0); - } - /** * Sets the native look of the target platform to not break the UI experience. Most of the UI * code is based on SWT which uses a platform native look. Currently, Windows 8&10, Windows 7, @@ -200,10 +140,4 @@ public abstract class AF3FXViewPart extends FXViewPart } return false; } - - /** {@inheritDoc} */ - @Override - public Node getLayout() { - return root; - } } diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/layout/.ratings b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/layout/.ratings index 5768ee00db3463b5ebc51fde8f4b435be521febc..79b0e1c557ccdd58082683085ecdd932da2bf4ca 100644 --- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/layout/.ratings +++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/layout/.ratings @@ -1,2 +1,2 @@ -CompositeFXControllerBase.java 7b4d3b7511e4ef146528cb2095856e4aa43e965f GREEN -ICompositeFXController.java d2c239d857aa1b125097fe0feb8ebb7dfe7f7072 GREEN +CompositeFXControllerBase.java 82fa7fdeb260e7469df2f7140a16b9b4201716cd YELLOW +ICompositeFXController.java 8da8c709bc6a8232f7d9dfc0a4e76cea2d6f6879 YELLOW diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/layout/CompositeFXControllerBase.java b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/layout/CompositeFXControllerBase.java index 7b4d3b7511e4ef146528cb2095856e4aa43e965f..82fa7fdeb260e7469df2f7140a16b9b4201716cd 100644 --- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/layout/CompositeFXControllerBase.java +++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/layout/CompositeFXControllerBase.java @@ -15,6 +15,10 @@ +--------------------------------------------------------------------------*/ package org.fortiss.tooling.common.ui.javafx.layout; +import static javafx.scene.layout.AnchorPane.setBottomAnchor; +import static javafx.scene.layout.AnchorPane.setLeftAnchor; +import static javafx.scene.layout.AnchorPane.setRightAnchor; +import static javafx.scene.layout.AnchorPane.setTopAnchor; import static org.fortiss.tooling.common.ui.javafx.util.JavaFXUtils.loadFXML; import java.io.IOException; @@ -22,6 +26,7 @@ import java.net.URL; import javafx.fxml.FXML; import javafx.scene.Node; +import javafx.scene.layout.AnchorPane; /** * JavaFX node which can be hierarchically composed. It can be included within another @@ -37,19 +42,32 @@ public abstract class CompositeFXControllerBase implements ICompositeFXControlle */ private Node layout; + /** + * {@link ICompositeFXController}s to be added to the {@link Node} by the + * {@code addContainments} method. + */ + private ICompositeFXController[] containments; + /** Constructor. */ - public CompositeFXControllerBase(CompositeFXControllerBase... containments) throws IOException { - URL fxmlResource = getClass().getResource(getFXMLLocation()); - layout = loadFXML(fxmlResource, this); - addContainments(containments); + public CompositeFXControllerBase(ICompositeFXController... containments) { + this.containments = containments; + this.layout = null; } - /** - * Returns a JavaFX {@link Node} with the layout specified in the {@link FXML} resource and - * associated with a controller of type {@code T}. - */ + /** {@inheritDoc} */ @Override - public Node getLayout() { + public Node getOrLoadLayout() { + if(layout == null) { + URL fxmlResource = getClass().getResource(getFXMLLocation()); + try { + layout = loadFXML(fxmlResource, this); + } catch(IOException e) { + throw new RuntimeException( + "Cannot load the resource located at " + getFXMLLocation(), e); + } + initialize(); + addContainments(containments); + } return layout; } @@ -60,4 +78,17 @@ public abstract class CompositeFXControllerBase implements ICompositeFXControlle /** {@inheritDoc} */ @Override public abstract void addContainments(ICompositeFXController[] containments); + + /** + * If the container is an {@link AnchorPane}, all margins are removed so as to fit the child to + * the anchor pane's size. + */ + protected void fitToParent(Node child) { + if(child.getParent() instanceof AnchorPane) { + setBottomAnchor(child, 0.0); + setTopAnchor(child, 0.0); + setLeftAnchor(child, 0.0); + setRightAnchor(child, 0.0); + } + } } diff --git a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/layout/ICompositeFXController.java b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/layout/ICompositeFXController.java index d2c239d857aa1b125097fe0feb8ebb7dfe7f7072..8da8c709bc6a8232f7d9dfc0a4e76cea2d6f6879 100644 --- a/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/layout/ICompositeFXController.java +++ b/org.fortiss.tooling.common.ui/src/org/fortiss/tooling/common/ui/javafx/layout/ICompositeFXController.java @@ -26,14 +26,16 @@ import javafx.scene.Node; public interface ICompositeFXController { /** - * Returns a JavaFX {@link Node} with the layout specified in the {@link FXML} resource and - * associated with a controller of type {@code T}. + * Loads the a JavaFX {@link Node} from the specified {@link FXML} resource. */ - public Node getLayout(); + public Node getOrLoadLayout(); /** Returns the location of the {@link FXML} resource with the view's layout. */ public String getFXMLLocation(); /** Adds the {@link ICompositeFXController}s to the container. */ public void addContainments(ICompositeFXController[] containments); + + /** Performs further actions on the layout. */ + public void initialize(); }