Moved Growl into it's own project

This commit is contained in:
nathan 2015-11-01 00:52:48 +01:00
parent 719d47c293
commit f382160189
4 changed files with 0 additions and 987 deletions

View File

@ -1,281 +0,0 @@
/**
* Copyright (c) 2014, 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, LLC
* 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 javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.image.ImageView;
import javafx.stage.Window;
import javafx.util.Duration;
import org.controlsfx.tools.Utils;
import java.util.ArrayList;
import java.util.List;
/**
* An API to show popup notification messages to the user in the corner of their
* screen, unlike the {@link org.controlsfx.control.NotificationPane} which shows notification messages
* within your application itself.
*
* <h3>Screenshot</h3>
* <p>
* The following screenshot shows a sample notification rising from the
* bottom-right corner of my screen:
*
* <br/>
* <br/>
* <img src="notifications.png"/>
*
* <h3>Code Example:</h3>
* <p>
* To create the notification shown in the screenshot, simply do the following:
*
* <pre>
* {@code
* Notifications.create()
* .title("Title Text")
* .text("Hello World 0!")
* .showWarning();
* }
* </pre>
*/
public class Growl {
/***************************************************************************
* * Static fields * *
**************************************************************************/
private static final String STYLE_CLASS_DARK = "dark"; //$NON-NLS-1$
/***************************************************************************
* * Private fields * *
**************************************************************************/
String title;
String text;
Node graphic;
Pos position = Pos.BOTTOM_RIGHT;
private Duration hideAfterDuration = Duration.seconds(5);
boolean hideCloseButton;
private EventHandler<ActionEvent> onAction;
Window owner;
List<String> styleClass = new ArrayList<>();
/***************************************************************************
* * Constructors * *
**************************************************************************/
// we do not allow instantiation of the Notifications class directly - users
// must go via the builder API (that is, calling create())
private
Growl() {
// no-op
}
/***************************************************************************
* * Public API * *
**************************************************************************/
/**
* Call this to begin the process of building a notification to show.
*/
public static
Growl create() {
// 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
});
return new Growl();
}
/**
* Specify the text to show in the notification.
*/
public
Growl text(String text) {
this.text = text;
return this;
}
/**
* Specify the title to show in the notification.
*/
public
Growl title(String title) {
this.title = title;
return this;
}
/**
* Specify the graphic to show in the notification.
*/
public
Growl graphic(Node graphic) {
this.graphic = graphic;
return this;
}
/**
* Specify the position of the notification on screen, by default it is
* {@link Pos#BOTTOM_RIGHT bottom-right}.
*/
public
Growl position(Pos position) {
this.position = position;
return this;
}
/**
* The dialog window owner - if specified the notifications will be inside
* the owner, otherwise the notifications will be shown within the whole
* screen.
*/
public
Growl owner(Object owner) {
this.owner = Utils.getWindow(owner);
return this;
}
/**
* Specify the duration that the notification should show, after which it
* will be hidden.
*/
public
Growl hideAfter(Duration duration) {
this.hideAfterDuration = duration;
return this;
}
/**
* Specify what to do when the user clicks on the notification (in addition
* to the notification hiding, which happens whenever the notification is
* clicked on).
*/
public
Growl onAction(EventHandler<ActionEvent> onAction) {
this.onAction = onAction;
return this;
}
/**
* Specify that the notification should use the built-in dark styling,
* rather than the default 'modena' notification style (which is a
* light-gray).
*/
public
Growl darkStyle() {
styleClass.add(STYLE_CLASS_DARK);
return this;
}
/**
* Specify that the close button in the top-right corner of the notification
* should not be shown.
*/
public
Growl hideCloseButton() {
this.hideCloseButton = true;
return this;
}
/**
* Instructs the notification to be shown, and that it should use the built-in 'warning' graphic.
*/
public
void showWarning() {
graphic(new ImageView(Growl.class.getResource("/org/controlsfx/dialog/dialog-warning.png")
.toExternalForm())); //$NON-NLS-1$
show();
}
/**
* Instructs the notification to be shown, and that it should use the built-in 'information' graphic.
*/
public
void showInformation() {
graphic(new ImageView(Growl.class.getResource("/org/controlsfx/dialog/dialog-information.png")
.toExternalForm())); //$NON-NLS-1$
show();
}
/**
* Instructs the notification to be shown, and that it should use the built-in 'error' graphic.
*/
public
void showError() {
graphic(new ImageView(Growl.class.getResource("/org/controlsfx/dialog/dialog-error.png")
.toExternalForm())); //$NON-NLS-1$
show();
}
/**
* Instructs the notification to be shown, and that it should use the built-in 'confirm' graphic.
*/
public
void showConfirm() {
graphic(new ImageView(Growl.class.getResource("/org/controlsfx/dialog/dialog-confirm.png")
.toExternalForm())); //$NON-NLS-1$
show();
}
/**
* Instructs the notification to be shown.
*/
public
void show() {
// we can't use regular popup, because IF WE HAVE NO OWNER, it won't work!
// instead, we just create a JFRAME (and use our StageViaSwing class) to put javaFX inside it
JavaFxUtil.invokeAndWait(() -> new GrowlPopup(this).show());
}
}

View File

@ -1,169 +0,0 @@
/**
* Copyright (c) 2014, ControlsFX All rights reserved.
* <p>
* 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.
* <p>
* 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.
* <p>
* MODIFIED BY DORKBOX, LLC Copyright 2015 dorkbox, llc
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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 javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
public
class GrowlNotification extends Region {
private static final double MIN_HEIGHT = 40;
private final String textText;
private final Node graphicNode;
protected final GridPane pane;
public
GrowlNotification(final Growl notification) {
this.textText = notification.text;
this.graphicNode = notification.graphic;
getStyleClass().add("notification-bar"); //$NON-NLS-1$
setVisible(true);
pane = new GridPane();
pane.getStyleClass()
.add("pane"); //$NON-NLS-1$
pane.setAlignment(Pos.BASELINE_LEFT);
getChildren().setAll(pane);
// put it all together
pane.getChildren()
.clear();
int row = 0;
// title
if (notification.title != null && !notification.title.isEmpty()) {
Label title = new Label();
title.getStyleClass()
.add("title"); //$NON-NLS-1$
title.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
GridPane.setHgrow(title, Priority.ALWAYS);
title.setText(notification.title);
pane.add(title, 0, row++);
}
Region spacer = new Region();
spacer.setPrefHeight(10);
pane.add(spacer, 0, row++);
// graphic + text area
Label label = new Label();
label.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
GridPane.setVgrow(label, Priority.ALWAYS);
GridPane.setHgrow(label, Priority.ALWAYS);
label.setText(textText);
label.setGraphic(graphicNode);
pane.add(label, 0, row);
// close button
if (!notification.hideCloseButton) {
Button closeBtn = new Button();
closeBtn.getStyleClass()
.setAll("close-button"); //$NON-NLS-1$
StackPane graphic = new StackPane();
graphic.getStyleClass()
.setAll("graphic"); //$NON-NLS-1$
closeBtn.setGraphic(graphic);
closeBtn.setMinSize(17, 17);
closeBtn.setPrefSize(17, 17);
GridPane.setMargin(closeBtn, new Insets(0, 0, 0, 8));
// position the close button in the best place, depending on the height
double minHeight = minHeight(-1);
GridPane.setValignment(closeBtn, minHeight == MIN_HEIGHT ? VPos.CENTER : VPos.TOP);
closeBtn.setOnAction(arg0 -> hide());
pane.add(closeBtn, 2, 0, 1, row + 1);
}
}
public
void hide() {
}
@Override
protected
void layoutChildren() {
final double w = getWidth();
double h = computePrefHeight(-1);
pane.resize(w, h);
}
@Override
protected
double computeMinWidth(double height) {
String text = textText;
Node graphic = graphicNode;
if ((text == null || text.isEmpty()) && (graphic != null)) {
return graphic.minWidth(height) + 20;
}
return 400;
}
@Override
protected
double computeMinHeight(double width) {
String text = textText;
Node graphic = graphicNode;
if ((text == null || text.isEmpty()) && (graphic != null)) {
return graphic.minHeight(width) + 20;
}
return 100;
}
@Override
protected
double computePrefHeight(double width) {
return Math.max(pane.prefHeight(width), minHeight(width));
}
}

View File

@ -1,467 +0,0 @@
package dorkbox.util.javafx;
import dorkbox.util.ScreenUtil;
import dorkbox.util.SwingUtil;
import javafx.animation.*;
import javafx.collections.ObservableList;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;
import org.controlsfx.tools.Utils;
import java.awt.*;
import java.awt.geom.*;
import java.util.ArrayList;
/**
*
*/
public
class GrowlPopup {
private static final java.util.List<GrowlPopup> popups = new ArrayList<>();
// for animating in the notifications
private static final ParallelTransition parallelTransition = new ParallelTransition();
private static final double padding = 40;
private final GrowlPopupViaSwing frame;
final double startX;
final double startY;
final javafx.stage.Window window;
final double screenWidth;
final double screenHeight;
private final Pos position;
private final double anchorX;
private final double anchorY;
final Timeline animationTimeline = new Timeline();
private double newX;
private double newY;
GrowlPopup(final Growl notification) {
final Image icon;
if (notification.graphic instanceof ImageView) {
icon = SwingFXUtils.fromFXImage(((ImageView) notification.graphic).getImage(), null);
} else {
icon = SwingUtil.BLANK_ICON;
}
// created on the swing EDT
frame = GrowlPopupViaSwing.create(icon, notification.title);
// don't actually show anything. This will be done by our own animator
frame.setShowAnimation(() -> {
frame.completeShowTransition();
});
// set screen position
final javafx.stage.Window owner = notification.owner;
if (owner == null) {
final Point mouseLocation = MouseInfo.getPointerInfo()
.getLocation();
final GraphicsDevice deviceAtMouse = ScreenUtil.getGraphicsDeviceAt(mouseLocation);
final Rectangle screenBounds = deviceAtMouse.getDefaultConfiguration()
.getBounds();
/*
* If the owner is not set, we work with the whole screen.
* EDIT: we use the screen that the mouse is currently on.
*/
startX = screenBounds.getX();
startY = screenBounds.getY();
screenWidth = screenBounds.getWidth();
screenHeight = screenBounds.getHeight();
window = Utils.getWindow(null);
}
else {
/*
* If the owner is set, we will make the notifications popup
* inside its window.
*/
startX = owner.getX();
startY = owner.getY();
screenWidth = owner.getWidth();
screenHeight = owner.getHeight();
window = owner;
}
// need to install our CSS
if (owner instanceof Stage) {
Scene ownerScene = owner.getScene();
ownerScene.getStylesheets()
.add(org.controlsfx.control.Notifications.class.getResource("notificationpopup.css")
.toExternalForm()); //$NON-NLS-1$
}
this.position = notification.position;
VBox region = new VBox();
final ObservableList<String> styleClass1 = region.getStyleClass();
styleClass1.add("notification-bar");
styleClass1.addAll(notification.styleClass);
region.setVisible(true);
region.setMinWidth(300);
region.setMinHeight(40);
GridPane pane = new GridPane();
pane.getStyleClass()
.add("pane");
pane.setAlignment(Pos.BASELINE_LEFT);
region.getChildren()
.add(pane);
// pane.setStyle("-fx-background-color: #2046ff;");
// title
if (notification.title != null && !notification.title.isEmpty()) {
javafx.scene.control.Label titleLabel = new javafx.scene.control.Label();
titleLabel.getStyleClass()
.add("title");
titleLabel.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
GridPane.setHgrow(titleLabel, Priority.ALWAYS);
titleLabel.setText(notification.title);
pane.add(titleLabel, 0, 0);
}
// close button
if (!notification.hideCloseButton) {
javafx.scene.control.Button closeBtn = new javafx.scene.control.Button();
closeBtn.getStyleClass()
.setAll("close-button");
StackPane graphic = new StackPane();
graphic.getStyleClass()
.setAll("graphic");
closeBtn.setGraphic(graphic);
closeBtn.setMinSize(17, 17);
closeBtn.setPrefSize(17, 17);
GridPane.setMargin(closeBtn, new javafx.geometry.Insets(0, 0, 0, 8));
// position the close button in the best place, depending on the height
double minHeight = pane.minHeight(-1);
GridPane.setValignment(closeBtn, minHeight == 40 ? VPos.CENTER : VPos.TOP);
closeBtn.setOnAction(arg0 -> createHideTimeline(Duration.ZERO).play());
pane.add(closeBtn, 2, 0, 1, 1);
}
// graphic + text area
javafx.scene.control.Label label = new javafx.scene.control.Label();
label.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
GridPane.setVgrow(label, Priority.ALWAYS);
GridPane.setHgrow(label, Priority.ALWAYS);
label.setText(notification.text);
label.setGraphic(notification.graphic);
label.setPadding(new javafx.geometry.Insets(10, 0, 10, 5));
pane.add(label, 0, 2);
region.setOnMouseClicked(e -> createHideTimeline(Duration.ZERO).play());
Scene scene = new Scene(region);
scene.getStylesheets()
.add(org.controlsfx.control.Notifications.class.getResource("notificationpopup.css")
.toExternalForm()); //$NON-NLS-1$
frame.setScene(scene);
frame.sizeToScene();
// determine location for the popup
final Dimension size = frame.getSize();
final double barWidth = size.getWidth();
final double barHeight = size.getHeight();
// get anchorX
switch (position) {
case TOP_LEFT:
case CENTER_LEFT:
case BOTTOM_LEFT:
anchorX = startX + padding;
break;
case TOP_CENTER:
case CENTER:
case BOTTOM_CENTER:
anchorX = startX + (screenWidth / 2.0) - barWidth / 2.0 - padding / 2.0;
break;
default:
case TOP_RIGHT:
case CENTER_RIGHT:
case BOTTOM_RIGHT:
anchorX = startX + screenWidth - barWidth - padding;
break;
}
// get anchorY
switch (position) {
case TOP_LEFT:
case TOP_CENTER:
case TOP_RIGHT:
anchorY = padding + startY;
break;
case CENTER_LEFT:
case CENTER:
case CENTER_RIGHT:
anchorY = startY + (screenHeight / 2.0) - barHeight / 2.0 - padding / 2.0;
break;
default:
case BOTTOM_LEFT:
case BOTTOM_CENTER:
case BOTTOM_RIGHT:
anchorY = startY + screenHeight - barHeight - padding;
break;
}
}
public
void show() {
this.newX = anchorX;
this.newY = anchorY;
frame.show(anchorX, anchorY);
addPopupToMap();
// begin a timeline to get rid of the popup (default is 5 seconds)
// if (notification.hideAfterDuration != Duration.INDEFINITE) {
// Timeline timeline = createHideTimeline(popup, growlNotification, p, notification.hideAfterDuration);
// timeline.play();
// }
}
@Override
public
boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final GrowlPopup that = (GrowlPopup) o;
return frame.equals(that.frame);
}
@Override
public
int hashCode() {
return frame.hashCode();
}
void close() {
// set it off screen (which is what the close method also does)
this.newX = Short.MIN_VALUE;
this.newY = Short.MIN_VALUE;
frame.close();
}
Dimension2D getSize() {
return frame.getSize();
}
void animateToTarget(final boolean shouldFadeIn, final double x, final double y) {
if (shouldFadeIn) {
if (frame.getOpacityProperty().getValue() == 0F) {
frame.setLocation((int)x, (int)y);
Timeline timeline = new Timeline();
timeline.getKeyFrames()
.addAll(new KeyFrame(Duration.millis(500), new KeyValue(frame.getOpacityProperty(), 1F, Interpolator.LINEAR)));
timeline.play();
}
} else {
frame.setLocation((int)x, (int)y);
// final boolean xEqual = x == frame.getX();
// final boolean yEqual = y == frame.getY();
//
// if (xEqual && yEqual) {
// return;
// }
//Transition t = new Transition() {
// {
// setCycleDuration(Duration.millis(500));
// }
//
// @Override
// protected
// void interpolate(final double frac) {
// final double y1 = frame.getY();
// final double distance = ((y-y1) * frac);
//
// frame.setLocation(x, y1 + distance);
// }
// };
// parallelTransition.getChildren().add(t);
}
// final ObservableList<KeyFrame> keyFrames = animationTimeline.getKeyFrames();
// keyFrames.clear();
//
// if (!xEqual) {
// keyFrames.addAll(new KeyFrame(Duration.millis(300), new KeyValue(xProperty, x, Interpolator.EASE_OUT)));
// }
// if (!yEqual) {
// keyFrames.addAll(new KeyFrame(Duration.millis(300), new KeyValue(yProperty, y, Interpolator.EASE_OUT)));
// }
//
// // x/y can change, keep running the animation until it's stable
// animationTimeline.setOnFinished(event -> animateToTarget(GrowlPopup.this.newX, GrowlPopup.this.newY));
// animationTimeline.playFromStart();
// }
// }
}
private
Timeline createHideTimeline(final Duration startDelay) {
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(500), new KeyValue(frame.getOpacityProperty(), 0.0F)));
timeline.setDelay(startDelay);
timeline.setOnFinished(e -> {
close();
removePopupFromMap();
});
return timeline;
}
// only called on the JavaFX app thread
private
void addPopupToMap() {
popups.add(this);
doAnimation(true);
}
// only called on the JavaFX app thread
private
void removePopupFromMap() {
popups.remove(this);
if (!popups.isEmpty()) {
doAnimation(false);
}
}
// only called on the JavaFX app thread
private static
void doAnimation(boolean shouldFadeIn) {
parallelTransition.stop();
parallelTransition.getChildren()
.clear();
// the logic for this, is that the first popup in place, doesn't move. EVERY other popup after it will be moved
// this behavior trickles down to the remaining popups, until all popups have been assigned new locations
final int length = popups.size();
final GrowlPopup[] copies = popups.toArray(new GrowlPopup[length]);
for (int i = 0; i < length; i++) {
final GrowlPopup popup = copies[i];
final boolean isShowFromTop = isShowFromTop(popup.position);
final Dimension2D size = popup.getSize();
final double x = popup.newX;
final double y = popup.newY;
final double width = size.getWidth();
final double height = size.getHeight();
if (isShowFromTop) {
for (int j = i+1; j < length; j++) {
final GrowlPopup copy = copies[j];
final Dimension2D size1 = copy.getSize();
final double x1 = copy.newX;
final double y1 = copy.newY;
final double width1 = size1.getWidth();
final double height1 = size1.getHeight();
if (intersectRect(x, y, width, height, x1, y1, width1, height1)) {
copy.newY = y + height + 10;
}
}
popup.animateToTarget(shouldFadeIn, popup.newX, popup.newY);
}
//
// // first one is always as base location with padding
// if (i == 0) {
// newY = 30 + _popup.startY;
// }
// else {
// // we add a little bit of padding, so they are not on top of eachother
// newY += popupHeight + 10;
// }
// }
// else {
// if (i == size - 1) {
//// newY = changedPopup.getTargetY() - popupHeight;
// }
// else {
// newY -= popupHeight;
// }
// }
//
// if (newY < 0) {
// System.err.println("closing");
// _popup.close();
// continue;
// }
// popup.animateToTarget(popup.anchorX, newY);
}
if (!parallelTransition.getChildren().isEmpty()) {
// parallelTransition.play();
}
}
static boolean intersectRect(double x1, double y1, double w1, double h1, double x2, double y2, double w2, double h2) {
return intersectRange(x1, x1+w1, x2, x2+w2) && intersectRange(y1, y1+h1, y2, y2+h2);
}
static boolean intersectRange(double ax1, double ax2, double bx1, double bx2) {
return Math.max(ax1, bx1) <= Math.min(ax2, bx2);
}
private static
boolean isShowFromTop(final Pos p) {
switch (p) {
case TOP_LEFT:
case TOP_CENTER:
case TOP_RIGHT:
return true;
default:
return false;
}
}
}

View File

@ -1,70 +0,0 @@
package dorkbox.util.javafx;
import dorkbox.util.SwingUtil;
import java.awt.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
*/
public
class GrowlPopupViaSwing extends StageViaSwing {
private static
AtomicInteger ID = new AtomicInteger(0);
@SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
static
GrowlPopupViaSwing create(final Image icon, final String title) {
final GrowlPopupViaSwing[] returnVal = new GrowlPopupViaSwing[1];
// this MUST happen on the EDT!
SwingUtil.invokeAndWait(() -> {
synchronized (returnVal) {
returnVal[0] = new GrowlPopupViaSwing(icon, title, ID.getAndIncrement());
}
});
synchronized (returnVal) {
return returnVal[0];
}
}
private final int id;
GrowlPopupViaSwing(final Image icon, final String title, final int ID) {
super();
this.id = ID;
frame.setAlwaysOnTop(true);
frame.setResizable(false);
frame.setIconImage(icon);
frame.setTitle(title);
}
@Override
public
boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final GrowlPopupViaSwing that = (GrowlPopupViaSwing) o;
return id == that.id;
}
@Override
public
int hashCode() {
return id;
}
}