adding sizeing features
diff --git a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/Util.java b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/Util.java
index c2b3fc7..d20d224 100644
--- a/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/Util.java
+++ b/bundles/runtime/org.eclipse.fx.ui.controls/src/org/eclipse/fx/ui/controls/Util.java
@@ -19,6 +19,7 @@
import java.util.List;
import java.util.Map;
import java.util.UUID;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -26,11 +27,16 @@
import org.eclipse.fx.core.Subscription;
import org.eclipse.fx.core.ThreadSynchronize.BlockCondition;
+import org.eclipse.fx.core.geom.Size;
+import org.eclipse.fx.core.text.TextUtil;
import org.eclipse.fx.ui.controls.styledtext.StyledString;
import org.eclipse.fx.ui.controls.styledtext.StyledStringSegment;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Platform;
@@ -44,10 +50,15 @@
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.BoundingBox;
+import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.Background;
+import javafx.scene.layout.BackgroundFill;
+import javafx.scene.layout.CornerRadii;
+import javafx.scene.paint.Paint;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
@@ -72,7 +83,7 @@
*
* @noreference
*/
- public static final boolean MNEMONICS_FIX = ! Boolean.getBoolean("efxclipse.mnemonicfix.disabled"); //$NON-NLS-1$
+ public static final boolean MNEMONICS_FIX = !Boolean.getBoolean("efxclipse.mnemonicfix.disabled"); //$NON-NLS-1$
/**
* Dump the scene graph to a formatted string
@@ -153,24 +164,24 @@
Iterator<Window> impl_getWindows = JavaFXCompatUtil.getAllWindows().iterator();
List<Window> sortedWindows = new ArrayList<>();
- Map<Window,List<Window>> parentChildRelation = new HashMap<>();
+ Map<Window, List<Window>> parentChildRelation = new HashMap<>();
- while( impl_getWindows.hasNext() ) {
+ while (impl_getWindows.hasNext()) {
Window window = impl_getWindows.next();
Window owner;
- if( window instanceof Stage ) {
- owner = ((Stage)window).getOwner();
- } else if( window instanceof PopupWindow ) {
- owner = ((PopupWindow)window).getOwnerWindow();
+ if (window instanceof Stage) {
+ owner = ((Stage) window).getOwner();
+ } else if (window instanceof PopupWindow) {
+ owner = ((PopupWindow) window).getOwnerWindow();
} else {
owner = null;
}
- if( owner == null ) {
+ if (owner == null) {
sortedWindows.add(window);
} else {
List<Window> list = parentChildRelation.get(owner);
- if( list == null ) {
+ if (list == null) {
list = new ArrayList<>();
parentChildRelation.put(owner, list);
}
@@ -178,10 +189,10 @@
}
}
- while( ! parentChildRelation.isEmpty() ) {
- for( Window rw : sortedWindows.toArray(new Window[0]) ) {
+ while (!parentChildRelation.isEmpty()) {
+ for (Window rw : sortedWindows.toArray(new Window[0])) {
List<Window> list = parentChildRelation.remove(rw);
- if( list != null ) {
+ if (list != null) {
sortedWindows.addAll(list);
}
}
@@ -189,7 +200,7 @@
Collections.reverse(sortedWindows);
- for( Window window : sortedWindows ) {
+ for (Window window : sortedWindows) {
if (!FIND_NODE_EXCLUDE.equals(window.getUserData()) && new BoundingBox(window.getX(), window.getY(), window.getWidth(), window.getHeight()).contains(screenX, screenY)) {
return findNode(window.getScene().getRoot(), screenX, screenY);
}
@@ -216,11 +227,10 @@
return rv;
}
Point2D b = n.screenToLocal(screenX, screenY);
- if (n.getBoundsInLocal().contains(b) && ! FIND_NODE_EXCLUDE.equals(n.getUserData())) {
+ if (n.getBoundsInLocal().contains(b) && !FIND_NODE_EXCLUDE.equals(n.getUserData())) {
rv = n;
if (n instanceof Parent) {
- List<Node> cList = ((Parent) n).getChildrenUnmodifiable()
- .stream().filter( no -> no.isVisible()).collect(Collectors.toList());
+ List<Node> cList = ((Parent) n).getChildrenUnmodifiable().stream().filter(no -> no.isVisible()).collect(Collectors.toList());
for (Node c : cList) {
Node cn = findNode(c, screenX, screenY);
@@ -274,7 +284,8 @@
* @param <E>
* the source type
* @return the subscription to dispose the binding
- * @deprecated use {@link FXObservableUtils#bindContent(List, ObservableList, Function)}
+ * @deprecated use
+ * {@link FXObservableUtils#bindContent(List, ObservableList, Function)}
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static <T, E> Subscription bindContent(List<T> target, ObservableList<E> sourceList, Function<E, T> converterFunction) {
@@ -474,18 +485,19 @@
/**
* Create a binding for text width calculation.
+ *
* @param text
* @param font
* @return
*/
public static DoubleBinding createTextWidthBinding(ObservableValue<String> text, ObservableValue<Font> font, ObservableValue<Number> fontZoomFactor) {
- return Bindings.createDoubleBinding(()->{
+ return Bindings.createDoubleBinding(() -> {
return getTextWidth(text.getValue(), font.getValue(), fontZoomFactor.getValue().doubleValue());
}, text, font, fontZoomFactor);
}
public static DoubleBinding createTextWidthBinding(String text, ObservableValue<Font> font, ObservableValue<Number> fontZoomFactor) {
- return Bindings.createDoubleBinding(()->{
+ return Bindings.createDoubleBinding(() -> {
return getTextWidth(text, font.getValue(), fontZoomFactor.getValue().doubleValue());
}, font, fontZoomFactor);
}
@@ -497,16 +509,90 @@
}
public static DoubleBinding createTextHeightBinding(String text, ObservableValue<Font> font, ObservableValue<Number> fontZoomFactor) {
- return Bindings.createDoubleBinding(()->{
+ return Bindings.createDoubleBinding(() -> {
return getTextHeight(text, font.getValue(), fontZoomFactor.getValue().doubleValue());
}, font, fontZoomFactor);
}
public static boolean isCopyEvent(MouseEvent event) {
- if( org.eclipse.fx.core.Util.isMacOS() ) {
+ if (org.eclipse.fx.core.Util.isMacOS()) {
return event.isAltDown();
} else {
return event.isControlDown();
}
}
+
+ private static Cache<CacheKey, Size> FONT_SIZE_CACHE;
+
+ private static class CacheKey {
+ private final Font f;
+ private final char c;
+
+ CacheKey(Font f, char c) {
+ this.f = f;
+ this.c = c;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + this.c;
+ result = prime * result + ((this.f == null) ? 0 : f.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ CacheKey other = (CacheKey) obj;
+ if (this.c != other.c)
+ return false;
+ if (this.f == null) {
+ if (other.f != null)
+ return false;
+ } else if (!this.f.equals(other.f))
+ return false;
+ return true;
+ }
+ }
+
+ /**
+ * Get the size for the provided character
+ *
+ * @param font
+ * the font
+ * @param c
+ * the character
+ * @return the size
+ */
+ public static Size getSize(Font font, char c) {
+ if (FONT_SIZE_CACHE == null) {
+ FONT_SIZE_CACHE = CacheBuilder.newBuilder().maximumSize(20).build();
+ }
+ Size rv = FONT_SIZE_CACHE.getIfPresent(new CacheKey(font, c));
+ if (rv == null) {
+ Text t = new Text(TextUtil.toString(c));
+ t.setFont(font);
+ FONT_SIZE_CACHE.put(new CacheKey(font, c), rv = new Size(t.prefWidth(-1), t.prefHeight(-1)));
+ }
+
+ return rv;
+ }
+
+ /**
+ * Create a simple background fill
+ *
+ * @param p
+ * the paint
+ * @return the background
+ */
+ public static Background getSimpleBackground(Paint p) {
+ return new Background(new BackgroundFill(p, CornerRadii.EMPTY, Insets.EMPTY));
+ }
}
\ No newline at end of file