Commit 2b65453d authored by Sarah Grebing's avatar Sarah Grebing

revert DockFX

parent ed95fcf7
package org.dockfx;
import java.util.LinkedList;
import java.util.Properties;
/**
* ContentHolder has common functions for storing persistent object for node
*
* @author HongKee Moon
*/
public class ContentHolder
{
/**
* The enum ContentHolder Type.
*/
public enum Type {
/**
* The SplitPane.
*/
SplitPane,
/**
* The TabPane.
*/
TabPane,
/**
* The Collection.
*/
Collection,
/**
* The FloatingNode.
*/
FloatingNode,
/**
* The DockNode.
*/
DockNode
}
String name;
Properties properties;
LinkedList children;
Type type;
public ContentHolder()
{
}
public ContentHolder( String name, Type type )
{
this.name = name;
this.properties = new Properties();
this.children = new LinkedList();
this.type = type;
}
public void addProperty( Object key, Object value )
{
properties.put( key, value );
}
public void addChild( Object child )
{
children.add( child );
}
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public Properties getProperties()
{
return properties;
}
public void setProperties( Properties properties )
{
this.properties = properties;
}
public LinkedList getChildren()
{
return children;
}
public void setChildren( LinkedList children )
{
this.children = children;
}
public Type getType()
{
return type;
}
public void setType( Type type )
{
this.type = type;
}
}
package org.dockfx;
/**
* To support the delayed open process for some specific applications, this interface implementation is used.
*/
public interface DelayOpenHandler {
public DockNode open(String nodeName);
}
...@@ -30,7 +30,7 @@ import javafx.scene.Node; ...@@ -30,7 +30,7 @@ import javafx.scene.Node;
import javafx.scene.input.PickResult; import javafx.scene.input.PickResult;
/** /**
* Base class for DockFX events. Each DockFX event has an associated event source, event target and * Base class for DockFX events. Each DockFX event has associated an event source, event target and
* an event type. The event source specifies for an event handler the object on which that handler * an event type. The event source specifies for an event handler the object on which that handler
* has been registered and which sent the event to it. The event target defines the path through * has been registered and which sent the event to it. The event target defines the path through
* which the event will travel when posted. The event type provides additional classification to * which the event will travel when posted. The event type provides additional classification to
......
...@@ -21,9 +21,14 @@ ...@@ -21,9 +21,14 @@
package org.dockfx; package org.dockfx;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Stack; import java.util.Stack;
import com.sun.javafx.stage.StageHelper;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.Event; import javafx.event.Event;
import javafx.event.EventHandler; import javafx.event.EventHandler;
...@@ -52,15 +57,15 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> { ...@@ -52,15 +57,15 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> {
/** /**
* The DockNode this node is a title bar for. * The DockNode this node is a title bar for.
*/ */
private DockNode dockNode; private final DockNode dockNode;
/** /**
* The label node used for captioning and the graphic. * The label node used for captioning and the graphic.
*/ */
private Label label; private final Label label;
/** /**
* State manipulation buttons including close, maximize, detach, and restore. * State manipulation buttons including close, maximize, detach, and restore.
*/ */
private Button closeButton, stateButton; private final Button closeButton, stateButton, minimizeButton;
/** /**
* Creates a default DockTitleBar with captions and dragging behavior. * Creates a default DockTitleBar with captions and dragging behavior.
...@@ -88,28 +93,67 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> { ...@@ -88,28 +93,67 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> {
closeButton = new Button(); closeButton = new Button();
closeButton.setOnAction(new EventHandler<ActionEvent>() { closeButton.setOnAction(new EventHandler<ActionEvent>() {
@Override @Override
public void handle(ActionEvent event) { public void handle(ActionEvent event) {
dockNode.close(); dockNode.close();
} }
}); });
closeButton.visibleProperty().bind(dockNode.closableProperty());
minimizeButton = new Button();
// create a pane that will stretch to make the buttons right aligned minimizeButton.setOnAction(new EventHandler<ActionEvent>() {
Pane fillPane = new Pane(); @Override
HBox.setHgrow(fillPane, Priority.ALWAYS); public void handle(ActionEvent event) {
dockNode.setMinimized(true);
getChildren().addAll(label, fillPane, stateButton, closeButton); }
});
this.addEventHandler(MouseEvent.MOUSE_PRESSED, this); this.addEventHandler(MouseEvent.MOUSE_PRESSED, this);
this.addEventHandler(MouseEvent.DRAG_DETECTED, this); this.addEventHandler(MouseEvent.DRAG_DETECTED, this);
this.addEventHandler(MouseEvent.MOUSE_DRAGGED, this); this.addEventHandler(MouseEvent.MOUSE_DRAGGED, this);
this.addEventHandler(MouseEvent.MOUSE_RELEASED, this); this.addEventHandler(MouseEvent.MOUSE_RELEASED, this);
label.getStyleClass().add("dock-title-label"); label.getStyleClass().add("dock-title-label");
closeButton.getStyleClass().add("dock-close-button"); closeButton.getStyleClass().add("dock-close-button");
stateButton.getStyleClass().add("dock-state-button"); stateButton.getStyleClass().add("dock-state-button");
minimizeButton.getStyleClass().add("dock-minimize-button");
this.getStyleClass().add("dock-title-bar"); this.getStyleClass().add("dock-title-bar");
// create a pane that will stretch to make the buttons right aligned
Pane fillPane = new Pane();
HBox.setHgrow(fillPane, Priority.ALWAYS);
dockNode.closableProperty().addListener( new ChangeListener< Boolean >()
{
@Override public void changed( ObservableValue< ? extends Boolean > observable, Boolean oldValue, Boolean newValue )
{
if(newValue)
{
if(!getChildren().contains( closeButton ))
getChildren().add( closeButton );
}
else
{
getChildren().removeIf( c -> c.equals( closeButton ) );
}
}
} );
dockNode.minimizableProperty().addListener( new ChangeListener< Boolean >()
{
@Override public void changed( ObservableValue< ? extends Boolean > observable, Boolean oldValue, Boolean newValue )
{
if(newValue)
{
getChildren().add(2, minimizeButton);
}
else
{
getChildren().remove( minimizeButton );
}
}
} );
getChildren().addAll( label, fillPane, stateButton, closeButton );
} }
/** /**
...@@ -149,6 +193,15 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> { ...@@ -149,6 +193,15 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> {
public final Button getStateButton() { public final Button getStateButton() {
return stateButton; return stateButton;
} }
/**
* The button used for minimizing this title bar and its associated dock node.
*
* @return The button used for minimizing this title bar and its associated dock node.
*/
public final Button getMinimizeButton() {
return minimizeButton;
}
/** /**
* The dock node that is associated with this title bar. * The dock node that is associated with this title bar.
...@@ -225,14 +278,10 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> { ...@@ -225,14 +278,10 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> {
// RFE for public scene graph traversal API filed but closed: // RFE for public scene graph traversal API filed but closed:
// https://bugs.openjdk.java.net/browse/JDK-8133331 // https://bugs.openjdk.java.net/browse/JDK-8133331
List<DockPane> dockPanes = DockPane.dockPanes; ObservableList<Stage> stages =
FXCollections.unmodifiableObservableList(StageHelper.getStages());
// fire the dock over event for the active stages // fire the dock over event for the active stages
for (DockPane dockPane : dockPanes) { for (Stage targetStage : stages) {
Window window = dockPane.getScene().getWindow();
if (!(window instanceof Stage)) continue;
Stage targetStage = (Stage) window;
// obviously this title bar does not need to receive its own events // obviously this title bar does not need to receive its own events
// though users of this library may want to know when their // though users of this library may want to know when their
// dock node is being dragged by subclassing it or attaching // dock node is being dragged by subclassing it or attaching
...@@ -303,7 +352,7 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> { ...@@ -303,7 +352,7 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> {
// then we need to offset the stage position by // then we need to offset the stage position by
// the height of this title bar // the height of this title bar
if (!dockNode.isCustomTitleBar() && dockNode.isDecorated()) { if (!dockNode.isCustomTitleBar() && dockNode.isDecorated()) {
dockNode.setFloating(true, new Point2D(0, DockTitleBar.this.getHeight())); dockNode.setFloating(true, new Point2D(0, DockTitleBar.this.getHeight()), null);
} else { } else {
dockNode.setFloating(true); dockNode.setFloating(true);
} }
...@@ -355,6 +404,12 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> { ...@@ -355,6 +404,12 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> {
Stage stage = dockNode.getStage(); Stage stage = dockNode.getStage();
Insets insetsDelta = this.getDockNode().getBorderPane().getInsets(); Insets insetsDelta = this.getDockNode().getBorderPane().getInsets();
// it is possible that drag start has not been set if some other node had focus when
// we started the drag
if (null == dragStart) {
dragStart = new Point2D(event.getX(), event.getY());
}
// dragging this way makes the interface more responsive in the event // dragging this way makes the interface more responsive in the event
// the system is lagging as is the case with most current JavaFX // the system is lagging as is the case with most current JavaFX
// implementations on Linux // implementations on Linux
...@@ -364,13 +419,13 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> { ...@@ -364,13 +419,13 @@ public class DockTitleBar extends HBox implements EventHandler<MouseEvent> {
// TODO: change the pick result by adding a copyForPick() // TODO: change the pick result by adding a copyForPick()
DockEvent dockEnterEvent = DockEvent dockEnterEvent =
new DockEvent(this, DockEvent.NULL_SOURCE_TARGET, DockEvent.DOCK_ENTER, event.getX(), new DockEvent(this, DockEvent.NULL_SOURCE_TARGET, DockEvent.DOCK_ENTER, event.getX(),
event.getY(), event.getScreenX(), event.getScreenY(), null); event.getY(), event.getScreenX(), event.getScreenY(), null, this.getDockNode());
DockEvent dockOverEvent = DockEvent dockOverEvent =
new DockEvent(this, DockEvent.NULL_SOURCE_TARGET, DockEvent.DOCK_OVER, event.getX(), new DockEvent(this, DockEvent.NULL_SOURCE_TARGET, DockEvent.DOCK_OVER, event.getX(),
event.getY(), event.getScreenX(), event.getScreenY(), null); event.getY(), event.getScreenX(), event.getScreenY(), null, this.getDockNode());
DockEvent dockExitEvent = DockEvent dockExitEvent =
new DockEvent(this, DockEvent.NULL_SOURCE_TARGET, DockEvent.DOCK_EXIT, event.getX(), new DockEvent(this, DockEvent.NULL_SOURCE_TARGET, DockEvent.DOCK_EXIT, event.getX(),
event.getY(), event.getScreenX(), event.getScreenY(), null); event.getY(), event.getScreenX(), event.getScreenY(), null, this.getDockNode());
EventTask eventTask = new EventTask() { EventTask eventTask = new EventTask() {
@Override @Override
......
...@@ -21,32 +21,35 @@ ...@@ -21,32 +21,35 @@
package org.dockfx.demo; package org.dockfx.demo;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Random; import java.util.Random;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.BorderPane;
import org.dockfx.DockNode; import org.dockfx.DockNode;
import org.dockfx.DockPane; import org.dockfx.DockPane;
import org.dockfx.DockPos; import org.dockfx.DockPos;
import javafx.application.Application; import javafx.application.Application;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.Separator;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
import javafx.scene.control.TabPane; import javafx.scene.control.TabPane;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView; import javafx.scene.control.TableView;
import javafx.scene.control.ToolBar;
import javafx.scene.control.TreeItem; import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView; import javafx.scene.control.TreeView;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.Priority; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.scene.web.HTMLEditor; import javafx.scene.web.HTMLEditor;
import javafx.stage.Stage; import javafx.stage.Stage;
...@@ -99,50 +102,63 @@ public class DockFX extends Application { ...@@ -99,50 +102,63 @@ public class DockFX extends Application {
DockNode tabsDock = new DockNode(tabs, "Tabs Dock", new ImageView(dockImage)); DockNode tabsDock = new DockNode(tabs, "Tabs Dock", new ImageView(dockImage));
tabsDock.setPrefSize(300, 100); tabsDock.setPrefSize(300, 100);
tabsDock.dock(dockPane, DockPos.TOP); tabsDock.dock(dockPane, DockPos.TOP);
DockNode tableDock = new DockNode(tableView);
// let's disable our table from being undocked DockNode tableDock = new DockNode(tableView, "Table");
tableDock.setDockTitleBar(null);
tableDock.setPrefSize(300, 100); tableDock.setPrefSize(300, 100);
tableDock.dock(dockPane, DockPos.BOTTOM); tableDock.dock(dockPane, DockPos.BOTTOM);
final Menu menu1 = new Menu("File"); MenuItem saveMenuItem = new MenuItem("Save");
final Menu menu2 = new Menu("Options"); saveMenuItem.setOnAction(new EventHandler<ActionEvent>() {
final Menu menu3 = new Menu("Help"); @Override
public void handle(ActionEvent event) {
MenuBar menuBar = new MenuBar(); if(dirExist(getUserDataDirectory()))
menuBar.getMenus().addAll(menu1, menu2, menu3); dockPane.storePreference(getUserDataDirectory() + "dock.pref");
}
ToolBar toolBar = new ToolBar( });
new Button("New"),
new Button("Open"), MenuItem restoreMenuItem = new MenuItem("Restore");
new Button("Save"), restoreMenuItem.setOnAction(new EventHandler<ActionEvent>() {
new Separator(), @Override
new Button("Clean"), public void handle(ActionEvent event) {
new Button("Compile"), dockPane.loadPreference(getUserDataDirectory() + "dock.pref");
new Button("Run"), }
new Separator(), });
new Button("Debug"),
new Button("Profile") Menu fileMenu = new Menu("File");
); MenuBar menuBar = new MenuBar(fileMenu);
fileMenu.getItems().addAll(saveMenuItem, restoreMenuItem);
VBox vbox = new VBox();
vbox.getChildren().addAll(menuBar, toolBar, dockPane); BorderPane mainBorderPane = new BorderPane();
VBox.setVgrow(dockPane, Priority.ALWAYS); mainBorderPane.setTop(menuBar);
mainBorderPane.setCenter(dockPane);
primaryStage.setScene(new Scene(vbox, 800, 500));
// show that overlays are relative to the docking area
mainBorderPane.setLeft(new AnchorPane(generateRandomTree()));
primaryStage.setScene(new Scene(mainBorderPane, 800, 500));
primaryStage.sizeToScene(); primaryStage.sizeToScene();
primaryStage.show(); primaryStage.show();
// can be created and docked before or after the scene is created // can be created and docked before or after the scene is created
// and the stage is shown // and the stage is shown
DockNode treeDock = new DockNode(generateRandomTree(), "Tree Dock", new ImageView(dockImage)); DockNode treeDock = new DockNode(generateRandomTree(), "Tree Dock1", new ImageView(dockImage));
treeDock.setPrefSize(100, 100); treeDock.setPrefSize(100, 100);
treeDock.dock(dockPane, DockPos.LEFT); treeDock.dock(dockPane, DockPos.LEFT);
treeDock = new DockNode(generateRandomTree(), "Tree Dock", new ImageView(dockImage)); treeDock = new DockNode(generateRandomTree(), "Tree Dock2", new ImageView(dockImage));
treeDock.setPrefSize(100, 100); treeDock.setPrefSize(100, 100);
treeDock.dock(dockPane, DockPos.RIGHT); treeDock.dock(dockPane, DockPos.RIGHT);
// If you want to get notified when the docknode is closed. You can add ChangeListener to DockNode's closedProperty()
treeDock.closedProperty().addListener( new ChangeListener< Boolean >()
{
@Override public void changed( ObservableValue< ? extends Boolean > observable, Boolean oldValue, Boolean newValue )
{
if(newValue)
System.out.println("TreeDock(DockPos.RIGHT) is closed.");
}
} );
// test the look and feel with both Caspian and Modena // test the look and feel with both Caspian and Modena
Application.setUserAgentStylesheet(Application.STYLESHEET_MODENA); Application.setUserAgentStylesheet(Application.STYLESHEET_MODENA);
// initialize the default styles for the dock pane and undocked nodes using the DockFX // initialize the default styles for the dock pane and undocked nodes using the DockFX
...@@ -175,4 +191,23 @@ public class DockFX extends Application { ...@@ -175,4 +191,23 @@ public class DockFX extends Application {
return treeView; return treeView;
} }
public static boolean dirExist(String dir)
{
String path = getUserDataDirectory();
if(!new File(path).exists())
return new File(path).mkdirs();
else
return true;
}
public static String getUserDataDirectory() {
return System.getProperty("user.home") + File.separator + ".dockfx" + File.separator
+ getApplicationVersionString() + File.separator;
}
public static String getApplicationVersionString() {
return "1.0";
}
} }
/**
* @file DockFX.java
* @brief Driver demonstrating basic dock layout with prototypes. Maintained in a separate package
* to ensure the encapsulation of org.dockfx private package members.
*
* @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 <http://www.gnu.org/licenses/>.
**/
package org.dockfx.demo;
import org.dockfx.DockPane;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.ToolBar;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.dockfx.DockNode;
import org.dockfx.DockPos;
/**
* This app creates two dock panes, one over the other. Nodes can be added to either.
* If dock pane A is "exclusive", then A will ignore nodes from B (because A is
* exclusive and won't accept nodes from any other dockpane, and B will ignore nodes
* from A because A is exclusive and won't let go of them.
*
* If neither A or B is exclusive, Issue #24 from RobertBColton/DockFX will occur.
* @author will
*/
public class TwoDockPanes extends Application {
public static void main(String[] args) {
launch(args);
}
private VBox vbox;
private DockPane dp1;
private DockPane dp2;