Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion core/src/main/java/software/coley/bentofx/Bento.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
import software.coley.bentofx.layout.container.DockContainerRootBranch;
import software.coley.bentofx.search.SearchHandler;

import java.util.Objects;

/**
* Top level controller for docking operations.
*
* @author Matt Coley
*/
public class Bento {
public class Bento implements Identifiable {
private final String identifier;
private final ObservableList<DockContainerRootBranch> rootContainers = FXCollections.observableArrayList();
private final ObservableList<DockContainerRootBranch> rootContainersView = FXCollections.unmodifiableObservableList(rootContainers);
private final EventBus eventBus = newEventBus();
Expand All @@ -33,6 +36,24 @@ public class Bento {
private final DockableDragDropBehavior dragDropBehavior = newDragDropBehavior();
private final DockableClickBehavior clickBehavior = newClickBehavior();

/**
* Creates a {@code Bento} with a generated identifier.
*/
public Bento() {
identifier = DockBuilding.uid("cbento");
}

/**
* Creates a {@code Bento} with the given identifier.
*
* @param identifier
* This bento's identifier.
*/
public Bento(final String identifier) {
Objects.requireNonNull(identifier, "identifier");
this.identifier = identifier;
}

protected EventBus newEventBus() {
return new EventBus();
}
Expand Down Expand Up @@ -159,4 +180,14 @@ public boolean unregisterRoot(DockContainerRootBranch container) {
}
return false;
}

/**
* {@return the identifier specified when creating this {@code Bento}}
* <p>
* This identifier is not guaranteed to be unique.
*/
@Override
public String getIdentifier() {
return identifier;
}
}
15 changes: 10 additions & 5 deletions core/src/main/java/software/coley/bentofx/Identifiable.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
package software.coley.bentofx;

import org.jspecify.annotations.Nullable;

/**
* Outline of an <i>(ideally uniquely)</i> identifiable object.
*
* @author Matt Coley
*/
public interface Identifiable {

/**
* @return This objects identifier.
* {@return This object's identifier.}
*/
String getIdentifier();

/**
* @param other
* Another identifiable object.
* {@return {@code true} when the other object has the same identifier.}
*
* @return {@code true} when the other object has the same identifier.
* @param other Another identifiable object.
*/
boolean matchesIdentity(Identifiable other);
default boolean matchesIdentity(final @Nullable Identifiable other) {
return other != null &&
this.getIdentifier().equals(other.getIdentifier());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public DockContainerLeaf leaf(String identifier) {
return new DockContainerLeaf(bento, identifier);
}

private static String uid(String prefix) {
public static String uid(String prefix) {
StringBuilder suffix = new StringBuilder(8);
for (int i = 0; i < 8; i++)
suffix.append((char) RANDOM.nextInt('A', 'Z'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import javafx.scene.layout.Region;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import org.jspecify.annotations.Nullable;
import software.coley.bentofx.building.StageBuilding;
import software.coley.bentofx.dockable.Dockable;
import software.coley.bentofx.layout.DockContainer;
Expand All @@ -22,7 +23,7 @@
*/
public class DragDropStage extends Stage {
private final boolean autoCloseWhenEmpty;
private WeakReference<Parent> content;
private @Nullable WeakReference<Parent> content;

/**
* @param autoCloseWhenEmpty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,6 @@ public String getIdentifier() {
return identifier;
}

@Override
public boolean matchesIdentity(Identifiable other) {
return getIdentifier().equals(other.getIdentifier());
}

/**
* @return Current title.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import javafx.scene.control.SplitPane;
import org.jspecify.annotations.Nullable;
import software.coley.bentofx.Bento;
import software.coley.bentofx.Identifiable;
import software.coley.bentofx.dockable.Dockable;
import software.coley.bentofx.event.DockEvent;
import software.coley.bentofx.layout.DockContainer;
Expand Down Expand Up @@ -502,11 +501,6 @@ public String getIdentifier() {
return identifier;
}

@Override
public boolean matchesIdentity(Identifiable other) {
return identifier.equals(other.getIdentifier());
}

@Override
protected void layoutChildren() {
super.layoutChildren();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
package software.coley.bentofx.layout.container;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.*;
import javafx.beans.value.ObservableObjectValue;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
Expand All @@ -18,7 +13,6 @@
import javafx.scene.layout.StackPane;
import org.jspecify.annotations.Nullable;
import software.coley.bentofx.Bento;
import software.coley.bentofx.Identifiable;
import software.coley.bentofx.control.Header;
import software.coley.bentofx.control.HeaderPane;
import software.coley.bentofx.control.canvas.PixelCanvas;
Expand Down Expand Up @@ -399,7 +393,7 @@ protected double getCollapsedSize() {
/**
* @return Uncollapsed size of this container.
*/
protected double getUncollapsedSize() {
public double getUncollapsedSize() {
return switch (getSide()) {
case TOP, BOTTOM -> uncollapsedHeight.get();
case LEFT, RIGHT -> uncollapsedWidth.get();
Expand Down Expand Up @@ -529,6 +523,34 @@ public void setCanSplit(boolean canSplit) {
canSplitProperty().set(canSplit);
}

/**
* Sets the size this container will occupy when it is uncollapsed. The public
* counterpart to {@link #getUncollapsedSize()}, intended for restoring a size
* that was recorded earlier - for instance by a layout persistence layer
* re-applying a saved layout.
* <p>
* While this container is uncollapsed the tracking properties are bound to its
* live width and height, so a value set here would be overwritten immediately
* and is ignored. Call this only while {@link #isCollapsed()} is {@code true},
* which is when the tracking properties are unbound and the value is the one
* that will be restored on expansion.
*
* @param size
* Size to occupy once uncollapsed.
*
* @return {@code true} when the size was applied, {@code false} when it was
* ignored because this container is not collapsed.
*
* @see #getUncollapsedSize()
*/
public boolean setUncollapsedSize(double size) {
if (uncollapsedWidth.isBound() || uncollapsedHeight.isBound())
return false;

updateCollapsedSize(size);
return true;
}

@Override
public Bento getBento() {
return bento;
Expand All @@ -539,11 +561,6 @@ public String getIdentifier() {
return identifier;
}

@Override
public boolean matchesIdentity(Identifiable other) {
return identifier.equals(other.getIdentifier());
}

@Override
public String toString() {
return "Container-Leaf:" + getIdentifier();
Expand Down
59 changes: 59 additions & 0 deletions core/src/test/java/software/coley/bentofx/IdentifiableTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package software.coley.bentofx;

import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Coverage for {@link Identifiable}'s default {@code matchesIdentity} method.
*
* @author Phil Bryant
*/
class IdentifiableTest {

private static final String IDENTIFIER = "identifiable-1";
private static final String OTHER_IDENTIFIER = "identifiable-2";

@Test
void matchesIdentityIsTrueWhenTheOtherObjectHasTheSameIdentifier() {
Identifiable subject = newIdentifiableImpl(IDENTIFIER);
Identifiable other = newIdentifiableImpl(IDENTIFIER);

assertThat(subject.matchesIdentity(other))
.describedAs("matchesIdentity() for two objects with the same identifier")
.isTrue();
}

@Test
void matchesIdentityIsFalseWhenTheOtherObjectHasADifferentIdentifier() {
Identifiable subject = newIdentifiableImpl(IDENTIFIER);
Identifiable other = newIdentifiableImpl(OTHER_IDENTIFIER);

assertThat(subject.matchesIdentity(other))
.describedAs("matchesIdentity() for objects with different identifiers")
.isFalse();
}

/**
* {@code matchesIdentity} widened its parameter to {@code @Nullable} - this
* is the defect that widening fixed: a {@code null} other used to be a
* {@code NullPointerException} risk, and must now just report no match.
*/
Comment thread
Col-E marked this conversation as resolved.
@Test
void matchesIdentityIsFalseWhenTheOtherObjectIsNull() {
Identifiable subject = newIdentifiableImpl(IDENTIFIER);

assertThat(subject.matchesIdentity(null))
.describedAs("matchesIdentity(null)")
.isFalse();
}

/**
* {@return an {@link Identifiable} whose {@link Identifiable#getIdentifier()} is the given identifier}
*
* @param identifier the identifier to return.
*/
private static Identifiable newIdentifiableImpl(final String identifier) {
return () -> identifier;
}
}
Loading