diff --git a/src/main/java/org/dockfx/DockNode.java b/src/main/java/org/dockfx/DockNode.java index 3dc097d..a628531 100644 --- a/src/main/java/org/dockfx/DockNode.java +++ b/src/main/java/org/dockfx/DockNode.java @@ -20,6 +20,8 @@ package org.dockfx; +import org.dockfx.viewControllers.BaseViewController; + import javafx.beans.property.BooleanProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleBooleanProperty; @@ -28,15 +30,19 @@ import javafx.beans.property.StringProperty; import javafx.css.PseudoClass; import javafx.event.EventHandler; +import javafx.fxml.FXMLLoader; +import javafx.geometry.Bounds; import javafx.geometry.Insets; import javafx.geometry.Point2D; import javafx.geometry.Rectangle2D; import javafx.scene.Cursor; import javafx.scene.Node; import javafx.scene.Scene; +import javafx.scene.control.Label; import javafx.scene.input.MouseEvent; import javafx.scene.layout.BorderPane; import javafx.scene.layout.Priority; +import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.stage.Screen; import javafx.stage.Stage; @@ -47,7 +53,7 @@ * Base class for a dock node that provides the layout of the content along with a title bar and a * styled border. The dock node can be detached and floated or closed and removed from the layout. * Dragging behavior is implemented through the title bar. - * + * * @since DockFX 0.1 */ public class DockNode extends VBox implements EventHandler { @@ -78,6 +84,11 @@ public class DockNode extends VBox implements EventHandler { */ private DockPane dockPane; + /** + * View controller of node inside this DockNode + */ + private BaseViewController viewController; + /** * CSS pseudo class selector representing whether this node is currently floating. */ @@ -93,7 +104,7 @@ public class DockNode extends VBox implements EventHandler { /** * Boolean property maintaining whether this node is currently maximized. - * + * * @defaultValue false */ private BooleanProperty maximizedProperty = new SimpleBooleanProperty(false) { @@ -107,9 +118,12 @@ protected void invalidated() { stage.setMaximized(get()); - // TODO: This is a work around to fill the screen bounds and not overlap the task bar when - // the window is undecorated as in Visual Studio. A similar work around needs applied for - // JFrame in Swing. http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4737788 + // TODO: This is a work around to fill the screen bounds and not overlap + // the task bar when + // the window is undecorated as in Visual Studio. A similar work around + // needs applied for + // JFrame in Swing. + // http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4737788 // Bug report filed: // https://bugs.openjdk.java.net/browse/JDK-8133330 if (this.get()) { @@ -134,7 +148,7 @@ public String getName() { /** * Creates a default DockNode with a default title bar and layout. - * + * * @param contents The contents of the dock node which may be a tree or another scene graph node. * @param title The caption title of this dock node which maintains bidirectional state with the * title bar and stage. @@ -142,21 +156,12 @@ public String getName() { * the title bar and stage. */ public DockNode(Node contents, String title, Node graphic) { - this.titleProperty.setValue(title); - this.graphicProperty.setValue(graphic); - this.contents = contents; - - dockTitleBar = new DockTitleBar(this); - - getChildren().addAll(dockTitleBar, contents); - VBox.setVgrow(contents, Priority.ALWAYS); - - this.getStyleClass().add("dock-node"); + initializeDockNode(contents, title, graphic); } /** * Creates a default DockNode with a default title bar and layout. - * + * * @param contents The contents of the dock node which may be a tree or another scene graph node. * @param title The caption title of this dock node which maintains bidirectional state with the * title bar and stage. @@ -167,17 +172,92 @@ public DockNode(Node contents, String title) { /** * Creates a default DockNode with a default title bar and layout. - * + * * @param contents The contents of the dock node which may be a tree or another scene graph node. */ public DockNode(Node contents) { this(contents, null, null); } + /** + * Creates a default DockNode with contents loaded from FXMLFile at provided path. + * + * @param FXMLPath path to fxml file. + * @param title The caption title of this dock node which maintains bidirectional state with the + * title bar and stage. + * @param graphic The caption title of this dock node which maintains bidirectional state with the + * title bar and stage. + */ + public DockNode(String FXMLPath, String title, Node graphic) { + FXMLLoader loader = loadNode(FXMLPath); + initializeDockNode(loader.getRoot(), title, graphic); + viewController = loader.getController(); + } + + /** + * Creates a default DockNode with contents loaded from FXMLFile at provided path. + * + * @param FXMLPath path to fxml file. + * @param title The caption title of this dock node which maintains bidirectional state with the + * title bar and stage. + */ + public DockNode(String FXMLPath, String title) { + this(FXMLPath, title, null); + } + + /** + * Creates a default DockNode with contents loaded from FXMLFile at provided path with default + * title bar. + * + * @param FXMLPath path to fxml file. + */ + public DockNode(String FXMLPath) { + this(FXMLPath, null, null); + } + + /** + * Loads Node from fxml file located at FXMLPath and returns it. + * + * @param FXMLPath Path to fxml file. + * @return Node loaded from fxml file or StackPane with Label with error message. + */ + private static FXMLLoader loadNode(String FXMLPath) { + FXMLLoader loader = new FXMLLoader(); + try { + loader.load(DockNode.class.getResourceAsStream(FXMLPath)); + } catch (Exception e) { + e.printStackTrace(); + loader.setRoot(new StackPane(new Label("Could not load FXML file"))); + } + return loader; + } + + /** + * Sets DockNodes contents, title and title bar graphic + * + * @param contents The contents of the dock node which may be a tree or another scene graph node. + * @param title The caption title of this dock node which maintains bidirectional state with the + * title bar and stage. + * @param graphic The caption title of this dock node which maintains bidirectional state with the + * title bar and stage. + */ + private void initializeDockNode(Node contents, String title, Node graphic) { + this.titleProperty.setValue(title); + this.graphicProperty.setValue(graphic); + this.contents = contents; + + dockTitleBar = new DockTitleBar(this); + + getChildren().addAll(dockTitleBar, contents); + VBox.setVgrow(contents, Priority.ALWAYS); + + this.getStyleClass().add("dock-node"); + } + /** * The stage style that will be used when the dock node is floating. This must be set prior to * setting the dock node to floating. - * + * * @param stageStyle The stage style that will be used when the node is floating. */ public void setStageStyle(StageStyle stageStyle) { @@ -186,7 +266,7 @@ public void setStageStyle(StageStyle stageStyle) { /** * Changes the contents of the dock node. - * + * * @param contents The new contents of this dock node. */ public void setContents(Node contents) { @@ -197,7 +277,7 @@ public void setContents(Node contents) { /** * Changes the title bar in the layout of this dock node. This can be used to remove the dock * title bar from the dock node by passing null. - * + * * @param dockTitleBar null The new title bar of this dock node, can be set null indicating no * title bar is used. */ @@ -217,7 +297,7 @@ public void setDockTitleBar(DockTitleBar dockTitleBar) { /** * Whether the node is currently maximized. - * + * * @param maximized Whether the node is currently maximized. */ public final void setMaximized(boolean maximized) { @@ -226,7 +306,7 @@ public final void setMaximized(boolean maximized) { /** * Whether the node is currently floating. - * + * * @param floating Whether the node is currently floating. * @param translation null The offset of the node after being set floating. Used for aligning it * with its layout bounds inside the dock pane when it becomes detached. Can be null @@ -255,8 +335,10 @@ public void setFloating(boolean floating, Point2D translation) { stage.initStyle(stageStyle); - // offset the new stage to cover exactly the area the dock was local to the scene - // this is useful for when the user presses the + sign and we have no information + // offset the new stage to cover exactly the area the dock was local to + // the scene + // this is useful for when the user presses the + sign and we have no + // information // on where the mouse was clicked Point2D stagePosition; if (this.isDecorated()) { @@ -333,7 +415,7 @@ public void setFloating(boolean floating, Point2D translation) { /** * Whether the node is currently floating. - * + * * @param floating Whether the node is currently floating. */ public void setFloating(boolean floating) { @@ -343,16 +425,25 @@ public void setFloating(boolean floating) { /** * The dock pane that was last associated with this dock node. Either the dock pane that it is * currently docked to or the one it was detached from. Can be null if the node was never docked. - * + * * @return The dock pane that was last associated with this dock node. */ public final DockPane getDockPane() { return dockPane; } + /** + * ViewController associated with this dock nodes contents, might be null + * + * @return ViewController associated with this dock nodes contents + */ + public final BaseViewController getViewController() { + return viewController; + } + /** * The dock title bar associated with this dock node. - * + * * @return The dock title bar associated with this node. */ public final DockTitleBar getDockTitleBar() { @@ -362,7 +453,7 @@ public final DockTitleBar getDockTitleBar() { /** * The stage associated with this dock node. Can be null if the dock node was never set to * floating. - * + * * @return The stage associated with this node. */ public final Stage getStage() { @@ -372,7 +463,7 @@ public final Stage getStage() { /** * The border pane used to parent this dock node when floating. Can be null if the dock node was * never set to floating. - * + * * @return The stage associated with this node. */ public final BorderPane getBorderPane() { @@ -381,7 +472,7 @@ public final BorderPane getBorderPane() { /** * The contents managed by this dock node. - * + * * @return The contents managed by this dock node. */ public final Node getContents() { @@ -391,7 +482,7 @@ public final Node getContents() { /** * Object property maintaining bidirectional state of the caption graphic for this node with the * dock title bar or stage. - * + * * @defaultValue null */ public final ObjectProperty graphicProperty() { @@ -416,7 +507,7 @@ public final void setGraphic(Node graphic) { /** * Boolean property maintaining bidirectional state of the caption title for this node with the * dock title bar or stage. - * + * * @defaultValue "Dock" */ public final StringProperty titleProperty() { @@ -442,7 +533,7 @@ public final void setTitle(String title) { * Boolean property maintaining whether this node is currently using a custom title bar. This can * be used to force the default title bar to show when the dock node is set to floating instead of * using native window borders. - * + * * @defaultValue true */ public final BooleanProperty customTitleBarProperty() { @@ -470,7 +561,7 @@ public final void setUseCustomTitleBar(boolean useCustomTitleBar) { /** * Boolean property maintaining whether this node is currently floating. - * + * * @defaultValue false */ public final BooleanProperty floatingProperty() { @@ -498,7 +589,7 @@ public final boolean isFloating() { /** * Boolean property maintaining whether this node is currently floatable. - * + * * @defaultValue true */ public final BooleanProperty floatableProperty() { @@ -525,7 +616,7 @@ public final void setFloatable(boolean floatable) { /** * Boolean property maintaining whether this node is currently closable. - * + * * @defaultValue true */ public final BooleanProperty closableProperty() { @@ -549,7 +640,7 @@ public final void setClosable(boolean closable) { /** * Boolean property maintaining whether this node is currently resizable. - * + * * @defaultValue true */ public final BooleanProperty resizableProperty() { @@ -574,7 +665,7 @@ public final void setStageResizable(boolean resizable) { /** * Boolean property maintaining whether this node is currently docked. This is used by the dock * pane to inform the dock node whether it is currently docked. - * + * * @defaultValue false */ public final BooleanProperty dockedProperty() { @@ -618,7 +709,7 @@ public final boolean isDecorated() { /** * Dock this node into a dock pane. - * + * * @param dockPane The dock pane to dock this node into. * @param dockPos The docking position relative to the sibling of the dock pane. * @param sibling The sibling node to dock this node relative to. @@ -630,7 +721,7 @@ public void dock(DockPane dockPane, DockPos dockPos, Node sibling) { /** * Dock this node into a dock pane. - * + * * @param dockPane The dock pane to dock this node into. * @param dockPos The docking position relative to the sibling of the dock pane. */ @@ -680,7 +771,7 @@ public void close() { /** * Gets whether the mouse is currently in this dock node's resize zone. - * + * * @return Whether the mouse is currently in this dock node's resize zone. */ public boolean isMouseResizeZone() { @@ -750,9 +841,12 @@ public void handle(MouseEvent event) { newWidth += sizeDelta.getX(); } - // TODO: find a way to do this synchronously and eliminate the flickering of moving the stage - // around, also file a bug report for this feature if a work around can not be found this - // primarily occurs when dragging north/west but it also appears in native windows and Visual + // TODO: find a way to do this synchronously and eliminate the flickering + // of moving the stage + // around, also file a bug report for this feature if a work around can + // not be found this + // primarily occurs when dragging north/west but it also appears in native + // windows and Visual // Studio, so not that big of a concern. // Bug report filed: // https://bugs.openjdk.java.net/browse/JDK-8133332 diff --git a/src/main/java/org/dockfx/demo/DockFX.java b/src/main/java/org/dockfx/demo/DockFX.java index 6810fff..71687d2 100644 --- a/src/main/java/org/dockfx/demo/DockFX.java +++ b/src/main/java/org/dockfx/demo/DockFX.java @@ -54,6 +54,8 @@ public static void main(String[] args) { public void start(Stage primaryStage) { primaryStage.setTitle("DockFX"); + primaryStage.setTitle("DockFX"); + // create a dock pane that will manage our dock nodes and handle the layout DockPane dockPane = new DockPane(); @@ -103,13 +105,16 @@ public void start(Stage primaryStage) { primaryStage.show(); + // loads interface from fxml file + DockNode loginDock = new DockNode("demo/LoginForm.fxml", "Personal info", new ImageView(dockImage)); + loginDock.setPrefSize(100, 100); + loginDock.dock(dockPane, DockPos.LEFT); + + // can be created and docked before or after the scene is created // and the stage is shown DockNode treeDock = new DockNode(generateRandomTree(), "Tree Dock", new ImageView(dockImage)); treeDock.setPrefSize(100, 100); - treeDock.dock(dockPane, DockPos.LEFT); - treeDock = new DockNode(generateRandomTree(), "Tree Dock", new ImageView(dockImage)); - treeDock.setPrefSize(100, 100); treeDock.dock(dockPane, DockPos.RIGHT); // test the look and feel with both Caspian and Modena diff --git a/src/main/java/org/dockfx/viewControllers/BaseViewController.java b/src/main/java/org/dockfx/viewControllers/BaseViewController.java new file mode 100644 index 0000000..11981d9 --- /dev/null +++ b/src/main/java/org/dockfx/viewControllers/BaseViewController.java @@ -0,0 +1,39 @@ +/** + * @file BaseViewController.java + * @brief Abstract class for View Controllers + * + * @section License + * + * This file is a part of the DockFX Library. Copyright (C) 2015 Robert B. Colton + * + * This program is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with this + * program. If not, see . + **/ + +package org.dockfx.viewControllers; + +import javafx.fxml.FXML; + +/** + * Abstract base class for View Controllers + * + * @since DockFX 0.1 + */ +abstract public class BaseViewController { + + /** + * Automatically called to initialize a controller after its root element has been completely + * processed. + */ + @FXML + abstract protected void initialize(); + +} diff --git a/src/main/java/org/dockfx/viewControllers/LoginFormViewController.java b/src/main/java/org/dockfx/viewControllers/LoginFormViewController.java new file mode 100644 index 0000000..e84b0d2 --- /dev/null +++ b/src/main/java/org/dockfx/viewControllers/LoginFormViewController.java @@ -0,0 +1,43 @@ +/** + * @file DockFX.java + * @brief Simple view controller demonstrating button action + * + * @section License + * + * This file is a part of the DockFX Library. Copyright (C) 2015 Robert B. Colton + * + * This program is free software: you can redistribute it and/or modify it under the terms + * of the GNU Lesser General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with this + * program. If not, see . + **/ + +package org.dockfx.viewControllers; + +import javafx.fxml.FXML; +import javafx.scene.control.Button; + +/** + * ViewController associated with LoginForm.fxml file. + * Association created via Scene Builder. + */ +public class LoginFormViewController extends BaseViewController { + + @FXML + private Button button; + + @Override + protected void initialize() { + button.setOnAction(e -> handleButtonClick()); + } + + private void handleButtonClick() { + button.setText("Submitted!"); + } +} diff --git a/src/main/resources/org/dockfx/demo/LoginForm.fxml b/src/main/resources/org/dockfx/demo/LoginForm.fxml new file mode 100644 index 0000000..7c1cb53 --- /dev/null +++ b/src/main/resources/org/dockfx/demo/LoginForm.fxml @@ -0,0 +1,21 @@ + + + + + + + + + +