From aa72b395937b7018f5b6fa69709602ed38f03103 Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 7 Mar 2016 03:00:32 +0100 Subject: [PATCH] Moved Network into it's own project --- Dorkbox-Util/src/dorkbox/util/JavaFxUtil.java | 105 -- .../dorkbox/util/javafx/StageViaSwing.java | 489 --------- .../src/dorkbox/util/javafx/Wizard.java | 999 ------------------ .../src/dorkbox/util/javafx/WizardPage.java | 206 ---- .../dorkbox/util/crypto/AesByteBufTest.java | 325 ------ 5 files changed, 2124 deletions(-) delete mode 100644 Dorkbox-Util/src/dorkbox/util/JavaFxUtil.java delete mode 100644 Dorkbox-Util/src/dorkbox/util/javafx/StageViaSwing.java delete mode 100644 Dorkbox-Util/src/dorkbox/util/javafx/Wizard.java delete mode 100644 Dorkbox-Util/src/dorkbox/util/javafx/WizardPage.java delete mode 100644 Dorkbox-Util/test/dorkbox/util/crypto/AesByteBufTest.java diff --git a/Dorkbox-Util/src/dorkbox/util/JavaFxUtil.java b/Dorkbox-Util/src/dorkbox/util/JavaFxUtil.java deleted file mode 100644 index 174cefe..0000000 --- a/Dorkbox-Util/src/dorkbox/util/JavaFxUtil.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2015 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.util; - -import javafx.application.Platform; - -import java.awt.*; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; - -/** - * - */ -public -class JavaFxUtil { - - public static final javafx.scene.text.Font DEFAULT_FONT = new javafx.scene.text.Font(13); - - - public static - void showOnSameScreenAsMouseCenter(javafx.stage.Window stage) { - Point mouseLocation = MouseInfo.getPointerInfo() - .getLocation(); - - GraphicsDevice deviceAtMouse = ScreenUtil.getGraphicsDeviceAt(mouseLocation); - Rectangle bounds = deviceAtMouse.getDefaultConfiguration() - .getBounds(); - - stage.setX(bounds.x + bounds.width / 2 - stage.getWidth() / 2); - stage.setY(bounds.y + bounds.height / 2 - stage.getHeight() / 2); - } - - public static - void showOnSameScreenAsMouse(javafx.stage.Window stage) { - Point mouseLocation = MouseInfo.getPointerInfo() - .getLocation(); - - GraphicsDevice deviceAtMouse = ScreenUtil.getGraphicsDeviceAt(mouseLocation); - - stage.setX(deviceAtMouse.getDefaultConfiguration() - .getBounds().x); - } - - public static void invokeAndWait(Runnable runnable) { - // run synchronously on JavaFX thread - if (Platform.isFxApplicationThread()) { - runnable.run(); - return; - } - - FutureTask future = new FutureTask(runnable, null); - Platform.runLater(future); - try { - future.get(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - } - - public static T invokeAndWait(Callable callable) { - // run synchronously on JavaFX thread - if (Platform.isFxApplicationThread()) { - try { - return (T) callable.call(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - FutureTask future = new FutureTask(callable); - Platform.runLater(future); - try { - return (T) future.get(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - return null; - } - - public static void invokeLater(Runnable runnable) { - if (Platform.isFxApplicationThread()) { - runnable.run(); - } else { - Platform.runLater(runnable); - } - } -} diff --git a/Dorkbox-Util/src/dorkbox/util/javafx/StageViaSwing.java b/Dorkbox-Util/src/dorkbox/util/javafx/StageViaSwing.java deleted file mode 100644 index db3e6b3..0000000 --- a/Dorkbox-Util/src/dorkbox/util/javafx/StageViaSwing.java +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright 2015 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.util.javafx; - -import com.sun.javafx.application.PlatformImpl; -import dorkbox.util.JavaFxUtil; -import dorkbox.util.NamedThreadFactory; -import dorkbox.util.ScreenUtil; -import dorkbox.util.SwingUtil; -import javafx.application.Platform; -import javafx.beans.value.WritableValue; -import javafx.embed.swing.JFXPanel; -import javafx.scene.Scene; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; - -/** - * This class is necessary, because JavaFX stage is crap on linux. This offers sort-of the same functionality, but via swing instead. - * Annoying caveat. All swing setters MUST happen on the EDT. - */ -@SuppressWarnings("unused") -public -class StageViaSwing { - public static final Executor frameDisposer = Executors.newSingleThreadExecutor(new NamedThreadFactory("Swing Disposer", - Thread.MIN_PRIORITY, - true)); - - - final JFrame frame; - final JFXPanel panel; - - private volatile boolean inNestedEventLoop = false; - private final CountDownLatch showLatch = new CountDownLatch(1); - private final CountDownLatch showAndWaitLatch = new CountDownLatch(1); - - final WritableValue opacityProperty; - - - @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") - static - StageViaSwing create() { - final StageViaSwing[] returnVal = new StageViaSwing[1]; - - // this MUST happen on the EDT! - SwingUtil.invokeAndWait(() -> { - synchronized (returnVal) { - returnVal[0] = new StageViaSwing(); - } - }); - - synchronized (returnVal) { - return returnVal[0]; - } - } - - /** - * Necessary for us to be able to size our frame based on it's content - */ - private static Method method; - static { - try { - method = Scene.class.getDeclaredMethod("preferredSize"); - method.setAccessible(true); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - - // make sure that javafx application thread is started - // Note that calling PlatformImpl.startup more than once is OK - PlatformImpl.startup(() -> { - // No need to do anything here - }); - } - - private volatile boolean center = false; - private volatile double x; - private volatile double y; - private volatile double width; - private volatile double height; - private volatile boolean closing; - private volatile boolean resizable; - - public - void setAlwaysOnTop(final boolean alwaysOnTop) { - frame.setAlwaysOnTop(alwaysOnTop); - } - - interface OnShowAnimation { - void doShow(); -} - - private OnShowAnimation showAnimation = null; - - - public - void setShowAnimation(final OnShowAnimation showAnimation) { - this.showAnimation = showAnimation; - } - - StageViaSwing() { - frame = new JFrame(); - panel = new JFXPanel(); - -// frame.setLayout(null); - frame.setUndecorated(true); - frame.setOpacity(0F); - frame.add(panel); - - - opacityProperty = new WritableValue() { - @Override - public Float getValue() { - return frame.getOpacity(); - } - - @Override - public void setValue(Float value) { - SwingUtil.invokeAndWait(() -> frame.setOpacity(value)); - } - }; - - - frame.addWindowListener(new WindowAdapter() { - public void windowOpened(WindowEvent e) { - if (showAnimation != null) { -// Thread thread = new Thread(() -> { -// try { - // If this runs now, it will bug out, and flash on the screen before we want it to. - // REALLY dumb, but we have to wait for the system to draw the window and finish BEFORE we move it - // otherwise, it'll 'flash' onscreen because it will still be in the middle of it's initial "on-show" animation. -// Thread.sleep(5000); - - if (!inNestedEventLoop) { - renderContents(); - } else { - // notify we are done showing, to prevent race conditions with the JFX app thread - // the show method continues - showLatch.countDown(); - } -// } catch(InterruptedException ignored) { -// } -// }); -// thread.setDaemon(true); -// thread.setName("Window centering"); -// thread.start(); - } else if (!inNestedEventLoop) { - renderContents(); - } else { - // notify we are done showing, to prevent race conditions with the JFX app thread - // the show method continues - showLatch.countDown(); - } - } - - private - void renderContents() { - sizeToScene(); - - SwingUtil.invokeLater(StageViaSwing.this::recheckSize); - - if (showAnimation == null) { - opacityProperty.setValue(1F); - completeShowTransition(); - } else { - showAnimation.doShow(); - } - } - }); - } - - - // absolutely stupid - swing doesn't want to be forced to a certain size, unless specific incantations are performed. These seem to work - void recheckSize() { - if (frame.getX() != x || frame.getY() != y || frame.getWidth() != width || frame.getHeight() != height) { -// System.err.println("FAILED SIZE CHECK"); -// System.err.println("SIZE: " + width + " : " + height); -// System.err.println("actual: " + frame.getWidth() + " " + frame.getHeight()); - - final Dimension size = new Dimension((int) width, (int) height); - if (!resizable) { - frame.setMinimumSize(size); - frame.setMaximumSize(size); - panel.setMinimumSize(size); - panel.setMaximumSize(size); - } - - panel.setPreferredSize(size); - frame.setPreferredSize(size); - - if (center) { - // same as in screenUtils, but here we set bound instead of just location - final Point mouseLocation = MouseInfo.getPointerInfo() - .getLocation(); - - final GraphicsDevice deviceAtMouse = ScreenUtil.getGraphicsDeviceAt(mouseLocation); - final Rectangle bounds = deviceAtMouse.getDefaultConfiguration() - .getBounds(); - - - panel.setBounds(bounds.x + (bounds.width / 2) - (int)width / 2, - bounds.y + (bounds.height / 2) - (int)height / 2, - (int)width, - (int)height); - - frame.setBounds(bounds.x + (bounds.width / 2) - (int)width / 2, - bounds.y + (bounds.height / 2) - (int)height / 2, - (int)width, - (int)height); - } else { - panel.setBounds((int) x, - (int) y, - (int) width, - (int) height); - frame.setBounds((int) x, - (int) y, - (int) width, - (int) height); - } - - frame.pack(); - frame.revalidate(); - frame.repaint(); - -// System.err.println("recheck SIZE: " + frame.getWidth() + " " + frame.getHeight()); -// System.err.println("recheck SIZE: " + panel.getWidth() + " " + frame.getHeight()); - } - } - - public final - void completeShowTransition() { - showLatch.countDown(); - } - - public - void setTitle(final String title) { - SwingUtil.invokeAndWait(() -> frame.setTitle(title)); - } - - public - String getTitle() { - return frame.getTitle(); - } - - - public - void close() { - closing = true; - - // "hide" it until we can properly do so. - SwingUtil.invokeAndWait(() -> { - frame.setOpacity(0F); - frame.setBounds(Short.MIN_VALUE, Short.MIN_VALUE, 0, 0); - //noinspection deprecation - frame.hide(); - }); - - frameDisposer.execute(() -> { - // stupid thing flashes on-screen if we run this right away... - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - SwingUtil.invokeLater(frame::dispose); - }); - - releaseLatch(showAndWaitLatch); - } - - private - void releaseLatch(final CountDownLatch latch) { - if (inNestedEventLoop) { - inNestedEventLoop = false; - - if (!Platform.isFxApplicationThread()) { - JavaFxUtil.invokeAndWait(() -> com.sun.javafx.tk.Toolkit.getToolkit().exitNestedEventLoop(StageViaSwing.this, null)); - } else { - com.sun.javafx.tk.Toolkit.getToolkit().exitNestedEventLoop(StageViaSwing.this, null); - } - } else { - latch.countDown(); - } - } - - public - void setSize(final double width, final double height) { - this.width = width; - this.height = height; - SwingUtil.invokeAndWait(() -> frame.setSize((int)width, (int)height)); - } - - public - void setResizable(final boolean resizable) { - this.resizable = resizable; - SwingUtil.invokeAndWait(() -> frame.setResizable(resizable)); - } - - public - void setApplicationIcon(final java.awt.Image icon) { - SwingUtil.invokeAndWait(() -> frame.setIconImage(icon)); - } - - public - void show(final double x, final double y) { - // we want to make sure we go BACK to this location when we show the JFRAME on screen - this.x = x; - this.y = y; - - show(); - } - - public - void showAndWait(final double x, final double y) { - // we want to make sure we go BACK to this location when we show the JFRAME on screen - this.x = x; - this.y = y; - - showAndWait(); - } - - public - void show() { - SwingUtil.invokeAndWait(() -> { - frame.setSize(0, 0); - frame.setVisible(false); - frame.setOpacity(0f); - frame.setBounds(Short.MIN_VALUE, Short.MIN_VALUE, 0, 0); - - frame.revalidate(); - frame.repaint(); - }); - - // Figure out the size of everything. Because JFXPanel DOES NOT do this. - - // wait until our show animation is complete. There is a small delay out of necessity - // false-positive - //noinspection Duplicates - if (Platform.isFxApplicationThread()) { - inNestedEventLoop = true; - - SwingUtil.invokeAndWait(() -> frame.setVisible(true)); - - try { - showLatch.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - inNestedEventLoop = false; - - sizeToScene(); - - SwingUtil.invokeAndWait(() -> { - if (showAnimation == null) { - opacityProperty.setValue(1F); - completeShowTransition(); - } else { - showAnimation.doShow(); - } - }); - } else { - SwingUtil.invokeAndWait(() -> frame.setVisible(true)); - - try { - showLatch.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public - void showAndWait() { - show(); - - // false-positive - //noinspection Duplicates - if (Platform.isFxApplicationThread()) { - inNestedEventLoop = true; - com.sun.javafx.tk.Toolkit.getToolkit().enterNestedEventLoop(this); - } else { - try { - showAndWaitLatch.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public - void initModality(final Dialog.ModalExclusionType modal) { - // we take in the javaFX modality, and pass it on to the correct swing version - JavaFxUtil.invokeAndWait(() -> frame.setModalExclusionType(modal)); - } - - public - void sizeToScene() { - SwingUtil.invokeAndWait(() -> { - frame.revalidate(); - frame.repaint(); - }); - - // Figure out the size of everything. Because JFXPanel DOES NOT do this. - // must be on the FX app thread - JavaFxUtil.invokeAndWait(() -> { - final Scene scene = panel.getScene(); - - try { - // use reflection. This is lame, but necessary. must be on the jfx thread - method.invoke(scene); - - width = scene.getWidth(); - height = scene.getHeight(); - } catch (InvocationTargetException | IllegalAccessException e) { - e.printStackTrace(); - } - }); - - SwingUtil.invokeAndWait(this::recheckSize); - } - - public - void setScene(final Scene scene) { - // must be on the JFX or EDT threads - if (!Platform.isFxApplicationThread() && !EventQueue.isDispatchThread()) { - JavaFxUtil.invokeAndWait(() -> panel.setScene(scene)); - } else { - panel.setScene(scene); - } - } - - public - WritableValue getOpacityProperty() { - return opacityProperty; - } - - public - void setLocation(final double x, final double y) { - // we want to make sure we go BACK to this location when we show the JFRAME on screen - if (x != this.x || y != this.y) { - this.x = x; - this.y = y; - - if (!closing) { - SwingUtil.invokeAndWait(() -> frame.setLocation((int)x, (int)y)); - } - } - } - - public - double getX() { - return x; - } - - public - double getY() { - return y; - } - - public - void center() { - this.center = true; - } - - public - Dimension getSize() { - return frame.getSize(); - } -} diff --git a/Dorkbox-Util/src/dorkbox/util/javafx/Wizard.java b/Dorkbox-Util/src/dorkbox/util/javafx/Wizard.java deleted file mode 100644 index e0b3d72..0000000 --- a/Dorkbox-Util/src/dorkbox/util/javafx/Wizard.java +++ /dev/null @@ -1,999 +0,0 @@ -/** - * Copyright (c) 2014, 2015 ControlsFX - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of ControlsFX, any associated website, nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL CONTROLSFX BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * MODIFIED BY DORKBOX - * Copyright 2015 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.util.javafx; - -import dorkbox.util.JavaFxUtil; -import dorkbox.util.SwingUtil; -import impl.org.controlsfx.ImplUtils; -import javafx.animation.*; -import javafx.beans.property.*; -import javafx.beans.value.ObservableValue; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.collections.ObservableMap; -import javafx.event.ActionEvent; -import javafx.event.Event; -import javafx.event.EventHandler; -import javafx.geometry.Insets; -import javafx.scene.Node; -import javafx.scene.Scene; -import javafx.scene.control.Button; -import javafx.scene.control.Dialog; -import javafx.scene.control.ToolBar; -import javafx.scene.input.KeyCode; -import javafx.scene.input.KeyEvent; -import javafx.scene.layout.*; -import javafx.scene.text.Font; -import javafx.scene.text.Text; -import javafx.util.Duration; -import org.controlsfx.control.PopOver; -import org.controlsfx.tools.ValueExtractor; -import org.controlsfx.validation.ValidationSupport; - -import java.util.*; -import java.util.function.BooleanSupplier; -import java.util.function.Consumer; - -/** - *

The API for creating multi-page Wizards, based on JavaFX {@link Dialog} API.
- * Wizard can be setup in following few steps:

- *

    - *
  • Design wizard pages by inheriting them from {@link WizardPage}
  • - *
  • Define wizard flow by implementing {@link org.controlsfx.dialog.Wizard.Flow}
  • - *
  • Create and instance of the Wizard and assign flow to it
  • - *
  • Execute the wizard using showAndWait method
  • - *
  • Values can be extracted from settings map by calling getSettings - *
- *

For simple, linear wizards, the {@link LinearFlow} can be used. - * It is a flow based on a collection of wizard pages. Here is the example:

- * - *
{@code // Create pages. Here for simplicity we just create and instance of WizardPane.
- * WizardPane page1 = new WizardPane();
- * WizardPane page2 = new WizardPane();
- * WizardPane page2 = new WizardPane();
- *
- * // create wizard
- * Wizard wizard = new Wizard();
- *
- * // create and assign the flow
- * wizard.setFlow(new LinearFlow(page1, page2, page3));
- *
- * // show wizard and wait for response
- * wizard.showAndWait().ifPresent(result -> {
- *     if (result == ButtonType.FINISH) {
- *         System.out.println("Wizard finished, settings: " + wizard.getSettings());
- *     }
- * });}
- * - *

For more complex wizard flows we suggest to create a custom ones, describing page traversal logic. - * Here is a simplified example:

- * - *
{@code Wizard.Flow branchingFlow = new Wizard.Flow() {
- *     public Optional advance(WizardPane currentPage) {
- *         return Optional.of(getNext(currentPage));
- *     }
- *
- *     public boolean canAdvance(WizardPane currentPage) {
- *         return currentPage != page3;
- *     }
- *
- *     private WizardPane getNext(WizardPane currentPage) {
- *         if ( currentPage == null ) {
- *             return page1;
- *         } else if ( currentPage == page1) {
- *             // skipNextPage() does not exist - this just represents that you
- *             // can add a conditional statement here to change the page.
- *             return page1.skipNextPage()? page3: page2;
- *         } else {
- *             return page3;
- *         }
- *     }
- * };}
- */ -@SuppressWarnings("unused") -public class Wizard { - final StageViaSwing stage = StageViaSwing.create(); - - private final Text headerText; - private final VBox center; - - private final ObservableMap settings = FXCollections.observableHashMap(); - - final Stack pageHistory = new Stack<>(); - Optional currentPage = Optional.empty(); - - private final BooleanProperty invalidProperty = new SimpleBooleanProperty(false); - private final StringProperty invalidPropertyStrings = new SimpleStringProperty(); - - - // Read settings activated by default for backward compatibility - private final BooleanProperty readSettingsProperty = new SimpleBooleanProperty(true); - - volatile boolean success = false; - - private final Button BUTTON_PREVIOUS = new Button("Previous"); - - private final Button BUTTON_NEXT = new Button("Next"); - private final EventHandler BUTTON_NEXT_EVENT_HANDLER = event -> { - if (event instanceof KeyEvent) { - final KeyCode code = ((KeyEvent)event).getCode(); - if (code == KeyCode.ENTER || code == KeyCode.SPACE) { - event.consume(); - goNext(); - } - } else { - event.consume(); - goNext(); - } - }; - - private final EventHandler BUTTON_FINISH_EVENT_HANDLER = event -> { - if (event instanceof KeyEvent) { - final KeyCode code = ((KeyEvent)event).getCode(); - if (code == KeyCode.ENTER || code == KeyCode.SPACE) { - event.consume(); - goFinish(); - } - } else { - event.consume(); - goFinish(); - } - }; - - private volatile boolean useSpecifiedSize = false; - - private final PopOver popOver; - private final Text popOverErrorText; - private final Font defaultHeaderFont; - private VBox graphicRegion; - - /************************************************************************** - * - * Constructors - * - **************************************************************************/ - - /** - * Creates an instance of the wizard with no title. - */ - public - Wizard() { - this(""); - } - - /** - * Creates an instance of the wizard with the given title. - * - * @param title The wizard title. - */ - public - Wizard(String title) { - stage.center(); - - stage.initModality(java.awt.Dialog.ModalExclusionType.APPLICATION_EXCLUDE); - setTitle(title); - - BUTTON_PREVIOUS.setDisable(true); - BUTTON_NEXT.setDisable(true); - - BUTTON_PREVIOUS.setId("prev-button"); - BUTTON_NEXT.setId("next-button"); - - BUTTON_PREVIOUS.addEventFilter(ActionEvent.ACTION, event -> { - event.consume(); - goPrev(); - }); - - BUTTON_PREVIOUS.addEventFilter(KeyEvent.KEY_PRESSED, event -> { - final KeyCode code = event.getCode(); - if (code == KeyCode.ENTER || code == KeyCode.SPACE) { - event.consume(); - goPrev(); - } - }); - - - - popOver = new PopOver(); - popOver.setDetachable(false); - popOver.setDetached(false); - popOver.setAutoHide(false); - - popOver.setArrowSize(12); - popOver.setArrowIndent(12); - popOver.setArrowLocation(PopOver.ArrowLocation.TOP_CENTER); - popOver.setCornerRadius(6); - - VBox content = new VBox(); - content.setPadding(new Insets(10)); - - popOverErrorText = new Text(); - popOverErrorText.setFont(new Font(12)); - - content.setPadding(new Insets(20, 10, 0, 10)); - content.getChildren() - .add(popOverErrorText); - - popOver.setContentNode(content); - - invalidPropertyStrings.addListener((observable, oldValue, newValue) -> { - validatePopover(newValue); - }); - - Consumer consumer = new Consumer() { - @Override - public - void accept(final WizardPage currentPage) { - if (currentPage.autoFocusNext) { - JavaFxUtil.invokeLater(BUTTON_NEXT::requestFocus); - } - } - }; - - invalidProperty.addListener((ObservableValue o, Boolean ov, Boolean nv) -> { - validateActionState(); - // the value is "invalid", so we want "!invalid" - if (ov && !nv) { - currentPage.ifPresent(consumer); - } - }); - - BorderPane borderPane = new BorderPane(); - - // Auto-sizing spacer - Region spacer = new Region(); - HBox.setHgrow(spacer, Priority.ALWAYS); - - - Button cancel = new Button("Cancel"); - cancel.addEventFilter(ActionEvent.ACTION, event -> { - success = false; - close(); - }); - - - ToolBar toolbar = new ToolBar(cancel, spacer, BUTTON_PREVIOUS, BUTTON_NEXT); - toolbar.setPadding(new Insets(8)); - borderPane.setBottom(toolbar); - - headerText = new Text(); - defaultHeaderFont = new Font(25); - headerText.setFont(defaultHeaderFont); - - graphicRegion = new VBox(); - - Region spacer2 = new Region(); - spacer2.setMinWidth(10); - - ToolBar region = new ToolBar(graphicRegion, spacer2, headerText); - region.setPadding(new Insets(15, 12, 15, 12)); - borderPane.setTop(region); - - center = new VBox(); - center.setMinSize(10, 10); - center.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); - // center.setStyle("-fx-background-color: #2046ff;"); - borderPane.setCenter(center); - - Scene scene = new Scene(borderPane); - stage.setSize(300, 140); - stage.setScene(scene); - stage.setResizable(false); // hide the minimize/maximize decorations - - - scene.setOnKeyPressed(ke -> { - if (ke.getCode() == KeyCode.ESCAPE) { - success = false; - close(); - } - }); - - //noinspection Duplicates - stage.setShowAnimation(() -> { - Timeline timeline = new Timeline(); - timeline.setCycleCount(1); - timeline.getKeyFrames() - .addAll(new KeyFrame(Duration.millis(500), new KeyValue(stage.getOpacityProperty(), 1F, Interpolator.EASE_OUT))); - // have to trigger that our animation is completed and the show() method may continue - timeline.setOnFinished(event -> stage.completeShowTransition()); - timeline.play(); - }); - } - - private - void validatePopover(final String newValue) { - if (newValue != null) { - currentPage.ifPresent(currentPage -> JavaFxUtil.invokeLater(() -> { - final PopOver popOver = this.popOver; - - this.popOverErrorText.setText(newValue); - - if (!popOver.isShowing()) { - popOver.setX(0); - popOver.setY(0); - popOver.show(BUTTON_NEXT, -10); - } - })); - } else { - popOver.hide(); - } - } - - /************************************************************************** - * - * Public API - * - **************************************************************************/ - - - /** - * Allows you to customize the width and height of the wizard. Must be set before the flow is set - */ - public final - void setSize(int width, int height) { - stage.setSize(width, height); - useSpecifiedSize = true; - } - - - /** - * Shows the wizard but does not wait for a user response (in other words, this brings up a non-blocking dialog). - */ - public final - void show() { - stage.show(); - } - - /** - * Shows the wizard and waits for the user response (in other words, brings up a blocking dialog, with the returned value (true=finished - * or false=cancel/close) - * - * @return An true/false depending on how they closed the wizard. - */ - public final - boolean showAndWait() { - stage.showAndWait(); - - return success; - } - - public - void close() { - stage.close(); - } - - /** - * The settings map is the place where all data from pages is kept once the user moves on from the page, assuming there is a {@link - * ValueExtractor} that is capable of extracting a value out of the various fields on the page. - */ - public final - ObservableMap getSettings() { - return settings; - } - - /** - * Goes to the next page, or finishes the wizard - */ - public - void goNext() { - JavaFxUtil.invokeLater(() -> { - currentPage.ifPresent(pageHistory::push); - currentPage = getFlow().advance(currentPage.orElse(null)); - updatePage(stage, true); - }); - } - - private - void goPrev() { - currentPage = Optional.ofNullable(pageHistory.isEmpty() ? null : pageHistory.pop()); - JavaFxUtil.invokeLater(() -> updatePage(stage, false)); - } - - private - void goFinish() { - success = true; - close(); - } - - /************************************************************************** - * - * Properties - * - **************************************************************************/ - - // --- title - - /** - * Return the title of the wizard. - */ - public final - String getTitle() { - return stage.getTitle(); - } - - /** - * Change the Title of the wizard. - */ - public final - void setTitle(String title) { - stage.setTitle(title); - } - - // --- flow - /** - * The {@link Flow} property represents the flow of pages in the wizard. - */ - private final - ObjectProperty flow = new SimpleObjectProperty(new LinearFlow()) { - @Override - protected - void invalidated() { - updatePage(stage, false); - } - - @Override - public - void set(Flow flow) { - super.set(flow); - pageHistory.clear(); - - if (flow != null) { - currentPage = flow.advance(currentPage.orElse(null)); - updatePage(stage, true); - } - } - }; - - public final - ObjectProperty flowProperty() { - return flow; - } - - /** - * Returns the currently set {@link Flow}, which represents the flow of pages in the wizard. - */ - public final - Flow getFlow() { - return flow.get(); - } - - /** - * Sets the {@link Flow}, which represents the flow of pages in the wizard. - */ - public final - void setFlow(Flow flow) { - JavaFxUtil.invokeAndWait(() -> this.flow.set(flow)); - } - - - // --- Properties - private static final Object USER_DATA_KEY = new Object(); - - // A map containing a set of properties for this Wizard - private ObservableMap properties; - - /** - * Returns an observable map of properties on this Wizard for use primarily by application developers - not to be confused with the - * {@link #getSettings()} map that represents the values entered by the user into the wizard. - * - * @return an observable map of properties on this Wizard for use primarily by application developers - */ - @SuppressWarnings("FieldRepeatedlyAccessedInMethod") - public final - ObservableMap getProperties() { - if (properties == null) { - properties = FXCollections.observableMap(new HashMap<>()); - } - return properties; - } - - /** - * Tests if this Wizard has properties. - * - * @return true if this Wizard has properties. - */ - public - boolean hasProperties() { - return properties != null && !properties.isEmpty(); - } - - - // --- UserData - - /** - * Returns a previously set Object property, or null if no such property has been set using the {@link #setUserData(Object)} method. - * - * @return The Object that was previously set, or null if no property has been set or if null was set. - */ - public - Object getUserData() { - return getProperties().get(USER_DATA_KEY); - } - - /** - * Convenience method for setting a single Object property that can be retrieved at a later date. This is functionally equivalent to - * calling the getProperties().put(Object key, Object value) method. This can later be retrieved by calling {@link #getUserData()}. - * - * @param value - * The value to be stored - this can later be retrieved by calling {@link #getUserData()}. - */ - public - void setUserData(Object value) { - getProperties().put(USER_DATA_KEY, value); - } - - /** - * Gets the value of the property {@code invalid}. - * - * @return The validation state - * - * @see #invalidProperty() - */ - public final - boolean isInvalid() { - return invalidProperty.get(); - } - - /** - * Sets the value of the property {@code invalid}. - * - * @param invalid - * The new validation state {@link #invalidProperty() } - */ - public final - void setInvalid(boolean invalid) { - invalidProperty.set(invalid); - } - - /** - * Property for overriding the individual validation state of this {@link org.controlsfx.dialog.Wizard}. Setting {@code invalid} to true - * will disable the next/finish Button and the user will not be able to advance to the next page of the {@link - * org.controlsfx.dialog.Wizard}. Setting {@code invalid} to false will enable the next/finish Button.

For example you can use - * the {@link ValidationSupport#invalidProperty()} of a page and bind it to the {@code invalid} property:
{@code - * wizard.invalidProperty().bind(page.validationSupport.invalidProperty()); } - * - * @return The validation state property - */ - public final - BooleanProperty invalidProperty() { - return invalidProperty; - } - - /** - * Gets the value of the property {@code readSettings}. - * - * @return The read-settings state - * - * @see #readSettingsProperty() - */ - public final - boolean isReadSettings() { - return readSettingsProperty.get(); - } - - /** - * Sets the value of the property {@code readSettings}. - * - * @param readSettings - * The new read-settings state - * - * @see #readSettingsProperty() - */ - public final - void setReadSettings(boolean readSettings) { - readSettingsProperty.set(readSettings); - } - - /** - * Property for overriding the individual read-settings state of this {@link org.controlsfx.dialog.Wizard}. Setting {@code readSettings} - * to true will enable the value extraction for this {@link org.controlsfx.dialog.Wizard}. Setting {@code readSettings} to false will - * disable the value extraction for this {@link org.controlsfx.dialog.Wizard}. - * - * @return The readSettings state property - */ - public final - BooleanProperty readSettingsProperty() { - return readSettingsProperty; - } - - - - /************************************************************************** - * Private implementation - **************************************************************************/ - boolean BUTTON_PREV_INIT = false; - boolean BUTTON_NEXT_INIT = false; - - void updatePage(StageViaSwing stage, boolean advancing) { - Flow flow = getFlow(); - if (flow == null) { - return; - } - - SequentialTransition sequentialTransition = new SequentialTransition(); - sequentialTransition.setCycleCount(1); - - Optional prevPage = Optional.ofNullable(pageHistory.isEmpty() ? null : pageHistory.peek()); - prevPage.ifPresent(page -> { - // if we are going forward in the wizard, we read in the settings - // from the page and store them in the settings map. - // If we are going backwards, we do nothing - // This is only performed if readSettings is true. - if (advancing && isReadSettings()) { - readSettings(page); - } - - // give the previous wizard page a chance to update the pages list - // based on the settings it has received - page.onExitingPage(this); - - invalidProperty.unbind(); - invalidPropertyStrings.unbind(); - - invalidProperty.set(false); - popOver.hide(); - - Timeline timeline = new Timeline(); - timeline.setCycleCount(1); - timeline.getKeyFrames() - .addAll(new KeyFrame(Duration.millis(200), - new KeyValue(stage.getOpacityProperty(), 0F, Interpolator.EASE_OUT))); - - timeline.setOnFinished(event -> currentPage.ifPresent(currentPage -> { - refreshCurrentPage(stage, currentPage); - - SwingUtil.invokeAndWait(() -> SwingUtil.showOnSameScreenAsMouseCenter(stage.frame)); - - Timeline timeline2 = new Timeline(); - timeline2.setCycleCount(1); - timeline2.getKeyFrames() - .addAll(new KeyFrame(Duration.millis(500), - new KeyValue(stage.getOpacityProperty(), 1F, Interpolator.EASE_OUT))); - timeline2.play(); - }) - ); - sequentialTransition.getChildren().add(timeline); - }); - - // only run this if we don't have a prev page, otherwise, we run this at the end of our animation - if (!prevPage.isPresent()) { - currentPage.ifPresent(currentPage -> refreshCurrentPage(stage, currentPage)); - } - - sequentialTransition.play(); - validateActionState(); - } - - private - void refreshCurrentPage(final StageViaSwing stage, final WizardPage currentPage) { - // put in default actions - if (!BUTTON_PREV_INIT) { - BUTTON_PREV_INIT = true; - BUTTON_PREVIOUS.setDisable(false); - } - if (!BUTTON_NEXT_INIT) { - BUTTON_NEXT_INIT = true; - BUTTON_NEXT.setDisable(false); - - BUTTON_NEXT.addEventFilter(ActionEvent.ACTION, BUTTON_NEXT_EVENT_HANDLER); - BUTTON_NEXT.addEventFilter(KeyEvent.KEY_PRESSED, BUTTON_NEXT_EVENT_HANDLER); - } - - // then give user a chance to modify the default actions - currentPage.onEnteringPage(this); - - invalidProperty.bind(currentPage.invalidProperty); - invalidPropertyStrings.bind(currentPage.invalidPropertyStrings); - - final Node firstFocusElement = currentPage.firstFocusElement; - if (firstFocusElement != null) { - JavaFxUtil.invokeLater(() -> { - if (isInvalid()) { - firstFocusElement.requestFocus(); - } - else { - JavaFxUtil.invokeLater(BUTTON_NEXT::requestFocus); - } - }); - } - else { - if (isInvalid()) { - JavaFxUtil.invokeLater(BUTTON_PREVIOUS::requestFocus); - } - else { - JavaFxUtil.invokeLater(BUTTON_NEXT::requestFocus); - } - } - - // and then switch to the new pane - if (currentPage.headerFont != null) { - headerText.setFont(currentPage.headerFont); - } - else { - headerText.setFont(defaultHeaderFont); - } - - if (currentPage.headerGraphic != null) { - graphicRegion.getChildren().setAll(currentPage.headerGraphic); - } else { - graphicRegion.getChildren().clear(); - } - - headerText.setText(currentPage.headerText); - ObservableList children = center.getChildren(); - children.clear(); - children.add(currentPage.anchorPane); - - if (!useSpecifiedSize) { - currentPage.anchorPane.autosize(); - - if (stage.frame.isShowing()) { - stage.sizeToScene(); - } - } - - JavaFxUtil.invokeAndWait(() -> { - if (isInvalid()) { - validatePopover(currentPage.invalidPropertyStrings.get()); - } else { - popOver.hide(); - } - }); - } - - private - void validateActionState() { - // Note that we put the 'next' and 'finish' actions at the beginning of - // the actions list, so that it takes precedence as the default button, - // over, say, cancel. We will probably want to handle this better in the - // future... - - if (!getFlow().canAdvance(currentPage.orElse(null))) { - BUTTON_NEXT.setText("Finish"); - BUTTON_NEXT.removeEventFilter(ActionEvent.ACTION, BUTTON_NEXT_EVENT_HANDLER); - BUTTON_NEXT.removeEventFilter(KeyEvent.KEY_PRESSED, BUTTON_NEXT_EVENT_HANDLER); - - BUTTON_NEXT.addEventFilter(ActionEvent.ACTION, BUTTON_FINISH_EVENT_HANDLER); - BUTTON_NEXT.addEventFilter(KeyEvent.KEY_PRESSED, BUTTON_FINISH_EVENT_HANDLER); - } - else { - if (!BUTTON_NEXT.getText() - .equals("Next")) { - BUTTON_NEXT.addEventFilter(ActionEvent.ACTION, BUTTON_NEXT_EVENT_HANDLER); - BUTTON_NEXT.addEventFilter(KeyEvent.KEY_PRESSED, BUTTON_NEXT_EVENT_HANDLER); - - BUTTON_NEXT.removeEventFilter(ActionEvent.ACTION, BUTTON_FINISH_EVENT_HANDLER); - BUTTON_NEXT.removeEventFilter(KeyEvent.KEY_PRESSED, BUTTON_FINISH_EVENT_HANDLER); - } - BUTTON_NEXT.setText("Next"); - } - - validateButton(BUTTON_PREVIOUS, pageHistory::isEmpty); - validateButton(BUTTON_NEXT, invalidProperty::get); - } - - // Functional design allows to delay condition evaluation until it is actually needed - private static - void validateButton(Button button, BooleanSupplier condition) { - if ( button != null ) { - boolean asBoolean = condition.getAsBoolean(); - button.setDisable(asBoolean); - } - } - - private int settingCounter; - - private - void readSettings(WizardPage page) { - // for now we cannot know the structure of the page, so we just drill down - // through the entire scenegraph (from page.anchorPane down) until we get - // to the leaf nodes. We stop only if we find a node that is a - // ValueContainer (either by implementing the interface), or being - // listed in the internal valueContainers map. - - settingCounter = 0; - checkNode(page.anchorPane); - } - - private - boolean checkNode(Node n) { - boolean success = readSetting(n); - - if (success) { - // we've added the setting to the settings map and we should stop drilling deeper - return true; - } - else { - /** - * go into children of this node (if possible) and see if we can get - * a value from them (recursively) We use reflection to fix - * https://bitbucket.org/controlsfx/controlsfx/issue/412 . - */ - List children = ImplUtils.getChildren(n, true); - - // we're doing a depth-first search, where we stop drilling down - // once we hit a successful read - boolean childSuccess = false; - for (Node child : children) { - childSuccess |= checkNode(child); - } - return childSuccess; - } - } - - private - boolean readSetting(Node n) { - if (n == null) { - return false; - } - - Object setting = ValueExtractor.getValue(n); - - if (setting != null) { - // save it into the settings map. - // if the node has an id set, we will use that as the setting name - String settingName = n.getId(); - - // but if the id is not set, we will use a generic naming scheme - if (settingName == null || settingName.isEmpty()) { - settingName = "page_" /*+ previousPageIndex*/ + ".setting_" + settingCounter; //$NON-NLS-1$ //$NON-NLS-2$ - } - - getSettings().put(settingName, setting); - - settingCounter++; - } - - return setting != null; - } - - public - void requestNextFocus() { - BUTTON_NEXT.requestFocus(); - } - - public - void requestPrevFocus() { - BUTTON_PREVIOUS.requestFocus(); - } - - - - /** - * You can add multiple images of different sizes and JavaFX will pick the one that fits best. Because you have different sizes - * in task bar and different in title bar. - */ - public - void setApplicationIcon(final java.awt.Image applicationIcon) { - stage.setApplicationIcon(applicationIcon); - } - - - /************************************************************************** - * - * Support classes - * - **************************************************************************/ - - - /** - * Represents the page flow of the wizard. It defines only methods required to move forward in the wizard logic, as backward movement is - * automatically handled by wizard itself, using internal page history. - */ - public - interface Flow { - - /** - * Advances the wizard to the next page if possible. - * - * @param currentPage - * The current wizard page - * - * @return {@link Optional} value containing the next wizard page. - */ - Optional advance(WizardPage currentPage); - - /** - * Check if advancing to the next page is possible - * - * @param currentPage - * The current wizard page - * - * @return true if it is possible to advance to the next page, false otherwise. - */ - boolean canAdvance(WizardPage currentPage); - } - - - /** - * LinearFlow is an implementation of the {@link org.controlsfx.dialog.Wizard.Flow} interface, designed to support the most common type - * of wizard flow - namely, a linear wizard page flow (i.e. through all pages in the order that they are specified). Therefore, this - * {@link Flow} implementation simply traverses a collections of {@link WizardPage WizardPanes}. - *

- *

For example of how to use this API, please refer to the {@link org.controlsfx.dialog.Wizard} documentation

- * - * @see org.controlsfx.dialog.Wizard - * @see WizardPage - */ - public static - class LinearFlow implements Wizard.Flow { - - private final List pages; - - /** - * Creates a new LinearFlow instance that will allow for stepping through the given collection of {@link WizardPage} instances. - */ - public - LinearFlow(Collection pages) { - this.pages = new ArrayList<>(pages); - } - - /** - * Creates a new LinearFlow instance that will allow for stepping through the given varargs array of {@link WizardPage} instances. - */ - public - LinearFlow(WizardPage... pages) { - this(Arrays.asList(pages)); - } - - /** - * {@inheritDoc} - */ - @Override - public - Optional advance(WizardPage currentPage) { - int pageIndex = pages.indexOf(currentPage); - return Optional.ofNullable(pages.get(++pageIndex)); - } - - /** - * {@inheritDoc} - */ - @Override - public - boolean canAdvance(WizardPage currentPage) { - int pageIndex = pages.indexOf(currentPage); - return pages.size() - 1 > pageIndex; - } - } -} diff --git a/Dorkbox-Util/src/dorkbox/util/javafx/WizardPage.java b/Dorkbox-Util/src/dorkbox/util/javafx/WizardPage.java deleted file mode 100644 index 3339db2..0000000 --- a/Dorkbox-Util/src/dorkbox/util/javafx/WizardPage.java +++ /dev/null @@ -1,206 +0,0 @@ -/** - * Copyright (c) 2014, 2015 ControlsFX - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of ControlsFX, any associated website, nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL CONTROLSFX BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * MODIFIED BY DORKBOX - * Copyright 2015 dorkbox, llc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package dorkbox.util.javafx; - -import dorkbox.util.JavaFxUtil; -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; -import javafx.beans.property.SimpleStringProperty; -import javafx.beans.property.StringProperty; -import javafx.beans.value.ObservableValue; -import javafx.geometry.Insets; -import javafx.scene.Node; -import javafx.scene.control.Control; -import javafx.scene.control.DialogPane; -import javafx.scene.layout.Priority; -import javafx.scene.layout.VBox; -import javafx.scene.text.Font; -import javafx.scene.text.Text; -import org.controlsfx.validation.ValidationMessage; -import org.controlsfx.validation.ValidationResult; -import org.controlsfx.validation.ValidationSupport; -import org.controlsfx.validation.Validator; - -import java.util.Collection; - -/** - * WizardPane is the base class for all wizard pages. The API is essentially the {@link DialogPane}, with the addition of convenience - * methods related to {@link #onEnteringPage(Wizard) entering} and {@link #onExitingPage(Wizard) exiting} the page. - */ -@SuppressWarnings("UnusedParameters") -public -class WizardPage { - - String headerText; - Font headerFont; - Node headerGraphic; - - Node anchorPane; - - Node firstFocusElement; - - final StringProperty invalidPropertyStrings = new SimpleStringProperty(); - final BooleanProperty invalidProperty = new SimpleBooleanProperty(); - final ValidationSupport validationSupport = new ValidationSupport(); - boolean autoFocusNext = false; - - /** - * Creates an instance of wizard pane. - */ - public - WizardPage() { - validationSupport.validationResultProperty() - .addListener((ObservableValue o, ValidationResult ov, ValidationResult nv) -> { - final Collection errors = nv.getErrors(); - - final boolean empty = errors.isEmpty(); - if (empty) { - invalidPropertyStrings.set(null); - } else { - String errorText = errors.iterator() - .next() - .getText() - .trim(); - - if (!errorText.equals(invalidPropertyStrings.get())) { - invalidPropertyStrings.set(errorText); - } - } - invalidProperty.set(!empty); - }); - } - - - - /** - * Called on entering a page. This is a good place to read values from wizard settings and assign them to controls on the page - * - * @param wizard - * which page will be used on - */ - public - void onEnteringPage(Wizard wizard) { - // no-op - } - - /** - * Called on existing the page. This is a good place to read values from page controls and store them in wizard settings - * - * @param wizard - * which page was used on - */ - public - void onExitingPage(Wizard wizard) { - // no-opd - } - - public - void setHeaderText(final String headerText) { - this.headerText = headerText; - } - - public - void setContent(final Node content) { - // make this content fill the parent (which is a vbox) - VBox.setVgrow(content, Priority.ALWAYS); - this.anchorPane = content; - } - - public - void setContentText(final String contentText) { - Text text = new Text(); - text.setFont(JavaFxUtil.DEFAULT_FONT); - text.setText(contentText); - - // we use a Vbox, so that the text starts at the topleft. - // if we used a stackpane, it would be centered in the parent node - VBox region = new VBox(); - region.setPadding(new Insets(6)); - - region.getChildren().add(text); - region.setMinSize(0, 0); - - // make this content fill the parent (which is a vbox) - VBox.setVgrow(region, Priority.ALWAYS); - this.anchorPane = region; - } - - - public - void setFirstFocusElement(final Node firstFocusElement) { - this.firstFocusElement = firstFocusElement; - } - - - public - void setHeaderFont(final Font headerFont) { - this.headerFont = headerFont; - } - - - public - void registerValidator(final Control control, final Validator validator) { - this.validationSupport.registerValidator(control, validator); - } - - /** - * Necessary for enabling the "Next/Finish" button when a task is complete. - */ - public - void bind(final ObservableValue invalidProperty) { - this.invalidProperty.bind(invalidProperty); - } - - /** - * Enables the wizard to automatically focus on the "Next" (or "Finish"), when this item is valid. - */ - public - void autoFocusNext() { - autoFocusNext = true; - } - - public - void setHeaderGraphic(final Node headerGraphic) { - this.headerGraphic = headerGraphic; - } -} diff --git a/Dorkbox-Util/test/dorkbox/util/crypto/AesByteBufTest.java b/Dorkbox-Util/test/dorkbox/util/crypto/AesByteBufTest.java deleted file mode 100644 index 26bdd23..0000000 --- a/Dorkbox-Util/test/dorkbox/util/crypto/AesByteBufTest.java +++ /dev/null @@ -1,325 +0,0 @@ - -package dorkbox.util.crypto; - -import dorkbox.util.crypto.bouncycastle.GCMBlockCipher_ByteBuf; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import org.bouncycastle.crypto.engines.AESFastEngine; -import org.bouncycastle.crypto.modes.GCMBlockCipher; -import org.bouncycastle.crypto.params.KeyParameter; -import org.bouncycastle.crypto.params.ParametersWithIV; -import org.junit.Test; - -import java.io.IOException; -import java.security.SecureRandom; -import java.util.Arrays; - -import static org.junit.Assert.fail; - -public class AesByteBufTest { - - org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(this.getClass()); - private static String entropySeed = "asdjhasdkljalksdfhlaks4356268909087s0dfgkjh255124515hasdg87"; - - private String text = "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya." + - "hello, my name is inigo montoya. hello, my name is inigo montoya. hello, my name is inigo montoya."; - - // test input smaller than block size - private byte[] bytes = "hello!".getBytes(); - - // test input larger than block size - private byte[] bytesLarge = text.getBytes(); - - @Test - public void AesGcmEncryptBothA() throws IOException { - - final byte[] SOURCE = bytesLarge; - - SecureRandom rand = new SecureRandom(entropySeed.getBytes()); - - final GCMBlockCipher_ByteBuf aesEngine1 = new GCMBlockCipher_ByteBuf(new AESFastEngine()); - final GCMBlockCipher aesEngine2 = new GCMBlockCipher(new AESFastEngine()); - - final byte[] key = new byte[32]; - final byte[] iv = new byte[16]; - - // note: the IV needs to be VERY unique! - rand.nextBytes(key); // 256bit key (32 bytes) - rand.nextBytes(iv); // 128bit block size (16 bytes) - - final ParametersWithIV aesIVAndKey = new ParametersWithIV(new KeyParameter(key), iv); - - ByteBuf source = Unpooled.wrappedBuffer(SOURCE); - int length = SOURCE.length; - ByteBuf encryptAES = Unpooled.buffer(1024); - int encryptLength = CryptoAES.encrypt(aesEngine1, aesIVAndKey, source, encryptAES, length, logger); - - byte[] encrypt = new byte[encryptLength]; - System.arraycopy(encryptAES.array(), 0, encrypt, 0, encryptLength); - - byte[] encrypt2 = CryptoAES.encrypt(aesEngine2, key, iv, SOURCE, logger); - - - if (Arrays.equals(SOURCE, encrypt)) { - fail("bytes should not be equal"); - } - - if (!Arrays.equals(encrypt, encrypt2)) { - fail("bytes not equal"); - } - } - - @Test - public void AesGcmEncryptBothB() throws IOException { - final byte[] SOURCE = bytes; - - SecureRandom rand = new SecureRandom(entropySeed.getBytes()); - - final GCMBlockCipher_ByteBuf aesEngine1 = new GCMBlockCipher_ByteBuf(new AESFastEngine()); - final GCMBlockCipher aesEngine2 = new GCMBlockCipher(new AESFastEngine()); - - final byte[] key = new byte[32]; - final byte[] iv = new byte[16]; - - // note: the IV needs to be VERY unique! - rand.nextBytes(key); // 256bit key (32 bytes) - rand.nextBytes(iv); // 128bit block size (16 bytes) - - final ParametersWithIV aesIVAndKey = new ParametersWithIV(new KeyParameter(key), iv); - - ByteBuf source = Unpooled.wrappedBuffer(SOURCE); - int length = SOURCE.length; - ByteBuf encryptAES = Unpooled.buffer(1024); - int encryptLength = CryptoAES.encrypt(aesEngine1, aesIVAndKey, source, encryptAES, length, logger); - - byte[] encrypt = new byte[encryptLength]; - System.arraycopy(encryptAES.array(), 0, encrypt, 0, encryptLength); - - - byte[] encrypt2 = CryptoAES.encrypt(aesEngine2, key, iv, SOURCE, logger); - - - if (Arrays.equals(SOURCE, encrypt)) { - fail("bytes should not be equal"); - } - - if (!Arrays.equals(encrypt, encrypt2)) { - fail("bytes not equal"); - } - } - - @Test - public void AesGcmEncryptBufOnly() throws IOException { - - SecureRandom rand = new SecureRandom(entropySeed.getBytes()); - - GCMBlockCipher_ByteBuf aesEngine1 = new GCMBlockCipher_ByteBuf(new AESFastEngine()); - GCMBlockCipher aesEngine2 = new GCMBlockCipher(new AESFastEngine()); - - byte[] key = new byte[32]; - byte[] iv = new byte[16]; - - // note: the IV needs to be VERY unique! - rand.nextBytes(key); // 256bit key (32 bytes) - rand.nextBytes(iv); // 128bit block size (16 bytes) - - ParametersWithIV aesIVAndKey = new ParametersWithIV(new KeyParameter(key), iv); - ByteBuf source = Unpooled.wrappedBuffer(bytes); - int length = bytes.length; - ByteBuf encryptAES = Unpooled.buffer(1024); - int encryptLength = CryptoAES.encrypt(aesEngine1, aesIVAndKey, source, encryptAES, length, logger); - - byte[] encrypt = new byte[encryptLength]; - System.arraycopy(encryptAES.array(), 0, encrypt, 0, encryptLength); - - - byte[] decrypt = CryptoAES.decrypt(aesEngine2, key, iv, encrypt, logger); - - - if (Arrays.equals(bytes, encrypt)) { - fail("bytes should not be equal"); - } - - if (!Arrays.equals(bytes, decrypt)) { - fail("bytes not equal"); - } - } - - @Test - public void AesGcmDecryptBothA() throws IOException { - - final byte[] SOURCE = bytesLarge; - - SecureRandom rand = new SecureRandom(entropySeed.getBytes()); - - final GCMBlockCipher aesEngine1 = new GCMBlockCipher(new AESFastEngine()); - final GCMBlockCipher_ByteBuf aesEngine2 = new GCMBlockCipher_ByteBuf(new AESFastEngine()); - - final byte[] key = new byte[32]; - final byte[] iv = new byte[16]; - - // note: the IV needs to be VERY unique! - rand.nextBytes(key); // 256bit key (32 bytes) - rand.nextBytes(iv); // 128bit block size (16 bytes) - - final byte[] encrypt = CryptoAES.encrypt(aesEngine1, key, iv, SOURCE, logger); - final ByteBuf encryptAES = Unpooled.wrappedBuffer(encrypt); - final int length = encrypt.length; - - byte[] decrypt1 = CryptoAES.decrypt(aesEngine1, key, iv, encrypt, logger); - - - ParametersWithIV aesIVAndKey = new ParametersWithIV(new KeyParameter(key), iv); - ByteBuf decryptAES = Unpooled.buffer(1024); - int decryptLength = CryptoAES.decrypt(aesEngine2, aesIVAndKey, encryptAES, decryptAES, length, logger); - byte[] decrypt2 = new byte[decryptLength]; - System.arraycopy(decryptAES.array(), 0, decrypt2, 0, decryptLength); - - - if (Arrays.equals(SOURCE, encrypt)) { - fail("bytes should not be equal"); - } - - if (!Arrays.equals(decrypt1, decrypt2)) { - fail("bytes not equal"); - } - - if (!Arrays.equals(SOURCE, decrypt1)) { - fail("bytes not equal"); - } - } - - @Test - public void AesGcmDecryptBothB() throws IOException { - - byte[] SOURCE = bytes; - - SecureRandom rand = new SecureRandom(entropySeed.getBytes()); - - final GCMBlockCipher aesEngine1 = new GCMBlockCipher(new AESFastEngine()); - final GCMBlockCipher_ByteBuf aesEngine2 = new GCMBlockCipher_ByteBuf(new AESFastEngine()); - - final byte[] key = new byte[32]; - final byte[] iv = new byte[16]; - - // note: the IV needs to be VERY unique! - rand.nextBytes(key); // 256bit key (32 bytes) - rand.nextBytes(iv); // 128bit block size (16 bytes) - - final byte[] encrypt = CryptoAES.encrypt(aesEngine1, key, iv, SOURCE, logger); - final ByteBuf encryptAES = Unpooled.wrappedBuffer(encrypt); - final int length = encrypt.length; - - - byte[] decrypt1 = CryptoAES.decrypt(aesEngine1, key, iv, encrypt, logger); - - - ParametersWithIV aesIVAndKey = new ParametersWithIV(new KeyParameter(key), iv); - ByteBuf decryptAES = Unpooled.buffer(1024); - int decryptLength = CryptoAES.decrypt(aesEngine2, aesIVAndKey, encryptAES, decryptAES, length, logger); - byte[] decrypt2 = new byte[decryptLength]; - System.arraycopy(decryptAES.array(), 0, decrypt2, 0, decryptLength); - - - if (Arrays.equals(SOURCE, encrypt)) { - fail("bytes should not be equal"); - } - - if (!Arrays.equals(decrypt1, decrypt2)) { - fail("bytes not equal"); - } - - if (!Arrays.equals(SOURCE, decrypt1)) { - fail("bytes not equal"); - } - } - - @Test - public void AesGcmDecryptBufOnlyA() throws IOException { - byte[] SOURCE = bytesLarge; - - SecureRandom rand = new SecureRandom(entropySeed.getBytes()); - - GCMBlockCipher aesEngine1 = new GCMBlockCipher(new AESFastEngine()); - GCMBlockCipher_ByteBuf aesEngine2 = new GCMBlockCipher_ByteBuf(new AESFastEngine()); - - byte[] key = new byte[32]; - byte[] iv = new byte[16]; - - // note: the IV needs to be VERY unique! - rand.nextBytes(key); // 256bit key (32 bytes) - rand.nextBytes(iv); // 128bit block size (16 bytes) - - - byte[] encrypt = CryptoAES.encrypt(aesEngine1, key, iv, SOURCE, logger); - ByteBuf encryptAES = Unpooled.wrappedBuffer(encrypt); - int length = encrypt.length; - - - ParametersWithIV aesIVAndKey = new ParametersWithIV(new KeyParameter(key), iv); - ByteBuf decryptAES = Unpooled.buffer(1024); - int decryptLength = CryptoAES.decrypt(aesEngine2, aesIVAndKey, encryptAES, decryptAES, length, logger); - byte[] decrypt = new byte[decryptLength]; - System.arraycopy(decryptAES.array(), 0, decrypt, 0, decryptLength); - - if (Arrays.equals(SOURCE, encrypt)) { - fail("bytes should not be equal"); - } - - if (!Arrays.equals(SOURCE, decrypt)) { - fail("bytes not equal"); - } - } - - @Test - public void AesGcmDecryptBufOnlyB() throws IOException { - byte[] SOURCE = bytes; - - SecureRandom rand = new SecureRandom(entropySeed.getBytes()); - - GCMBlockCipher aesEngine1 = new GCMBlockCipher(new AESFastEngine()); - GCMBlockCipher_ByteBuf aesEngine2 = new GCMBlockCipher_ByteBuf(new AESFastEngine()); - - byte[] key = new byte[32]; - byte[] iv = new byte[16]; - - // note: the IV needs to be VERY unique! - rand.nextBytes(key); // 256bit key (32 bytes) - rand.nextBytes(iv); // 128bit block size (16 bytes) - - - byte[] encrypt = CryptoAES.encrypt(aesEngine1, key, iv, SOURCE, logger); - ByteBuf encryptAES = Unpooled.wrappedBuffer(encrypt); - int length = encrypt.length; - - - ParametersWithIV aesIVAndKey = new ParametersWithIV(new KeyParameter(key), iv); - ByteBuf decryptAES = Unpooled.buffer(1024); - int decryptLength = CryptoAES.decrypt(aesEngine2, aesIVAndKey, encryptAES, decryptAES, length, logger); - byte[] decrypt = new byte[decryptLength]; - System.arraycopy(decryptAES.array(), 0, decrypt, 0, decryptLength); - - if (Arrays.equals(SOURCE, encrypt)) { - fail("bytes should not be equal"); - } - - if (!Arrays.equals(SOURCE, decrypt)) { - fail("bytes not equal"); - } - } -}