소스 검색

:recycle: MFXComboBox, MFXComboBoxSkin, MFXFilterComboBoxSkin: improvement for issue #243, allow to easily dimension the combo popup by setting the number of rows to show in the list
:recycle: MFXFilterComboBoxSkin: do not create a new instance of SimpleVirtualFlow, use the one in the superclass instead
:truck: Renamed GenericAddRemoveChange to NonIterableChange as it was causing compilation issues from time to time

Signed-off-by: Alessadro Parisi <alessandro.parisi406@gmail.com>

Alessadro Parisi 2 년 전
부모
커밋
b9cf071b9a

+ 0 - 0
materialfx/src/main/java/io/github/palexdev/materialfx/collections/GenericAddRemoveChange.java → materialfx/src/main/java/io/github/palexdev/materialfx/collections/NonIterableChange.java


+ 31 - 1
materialfx/src/main/java/io/github/palexdev/materialfx/controls/MFXComboBox.java

@@ -26,6 +26,7 @@ import io.github.palexdev.materialfx.beans.properties.functional.BiFunctionPrope
 import io.github.palexdev.materialfx.beans.properties.functional.ConsumerProperty;
 import io.github.palexdev.materialfx.beans.properties.functional.FunctionProperty;
 import io.github.palexdev.materialfx.beans.properties.styleable.StyleableBooleanProperty;
+import io.github.palexdev.materialfx.beans.properties.styleable.StyleableIntegerProperty;
 import io.github.palexdev.materialfx.controls.base.MFXCombo;
 import io.github.palexdev.materialfx.controls.cell.MFXComboBoxCell;
 import io.github.palexdev.materialfx.font.MFXFontIcon;
@@ -387,6 +388,13 @@ public class MFXComboBox<T> extends MFXTextField implements MFXCombo<T> {
 	//================================================================================
 	// Styleable Properties
 	//================================================================================
+	private final StyleableIntegerProperty rowsCount = new StyleableIntegerProperty(
+			StyleableProperties.ROWS_COUNT,
+			this,
+			"rowsCount",
+			10
+	);
+
 	private final StyleableBooleanProperty scrollOnOpen = new StyleableBooleanProperty(
 			StyleableProperties.SCROLL_ON_OPEN,
 			this,
@@ -394,6 +402,21 @@ public class MFXComboBox<T> extends MFXTextField implements MFXCombo<T> {
 			false
 	);
 
+	public int getRowsCount() {
+		return rowsCount.get();
+	}
+
+	/**
+	 * Specifies the number of rows to show in the list, this determines the height of the popup.
+	 */
+	public StyleableIntegerProperty rowsCountProperty() {
+		return rowsCount;
+	}
+
+	public void setRowsCount(int rowsCount) {
+		this.rowsCount.set(rowsCount);
+	}
+
 	public boolean isScrollOnOpen() {
 		return scrollOnOpen.get();
 	}
@@ -417,6 +440,13 @@ public class MFXComboBox<T> extends MFXTextField implements MFXCombo<T> {
 		private static final StyleablePropertyFactory<MFXComboBox<?>> FACTORY = new StyleablePropertyFactory<>(MFXTextField.getClassCssMetaData());
 		private static final List<CssMetaData<? extends Styleable, ?>> cssMetaDataList;
 
+		private static final CssMetaData<MFXComboBox<?>, Number> ROWS_COUNT =
+				FACTORY.createSizeCssMetaData(
+						"-mfx-rows-count",
+						MFXComboBox::rowsCountProperty,
+						10
+				);
+
 		private static final CssMetaData<MFXComboBox<?>, Boolean> SCROLL_ON_OPEN =
 				FACTORY.createBooleanCssMetaData(
 						"-mfx-scroll-on-open",
@@ -427,7 +457,7 @@ public class MFXComboBox<T> extends MFXTextField implements MFXCombo<T> {
 		static {
 			cssMetaDataList = StyleablePropertiesUtils.cssMetaDataList(
 					MFXTextField.getClassCssMetaData(),
-					SCROLL_ON_OPEN
+					ROWS_COUNT, SCROLL_ON_OPEN
 			);
 		}
 	}

+ 23 - 0
materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXComboBoxSkin.java

@@ -23,6 +23,9 @@ import io.github.palexdev.materialfx.selection.ComboBoxSelectionModel;
 import io.github.palexdev.materialfx.utils.AnimationUtils;
 import io.github.palexdev.virtualizedfx.cell.Cell;
 import io.github.palexdev.virtualizedfx.flow.simple.SimpleVirtualFlow;
+import javafx.beans.binding.Bindings;
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.SimpleBooleanProperty;
 import javafx.event.ActionEvent;
 import javafx.event.Event;
 import javafx.event.EventHandler;
@@ -50,6 +53,8 @@ public class MFXComboBoxSkin<T> extends MFXTextFieldSkin {
 	//================================================================================
 	protected final MFXPopup popup;
 	private EventHandler<MouseEvent> popupManager;
+
+	protected final BooleanProperty vfInitialized = new SimpleBooleanProperty(false);
 	protected SimpleVirtualFlow<T, Cell<T>> virtualFlow;
 
 	//================================================================================
@@ -258,6 +263,16 @@ public class MFXComboBoxSkin<T> extends MFXTextFieldSkin {
 			};
 			virtualFlow.cellFactoryProperty().bind(comboBox.cellFactoryProperty());
 			virtualFlow.prefWidthProperty().bind(comboBox.widthProperty());
+
+			Runnable createBinding = () ->
+					virtualFlow.prefHeightProperty().bind(Bindings.createDoubleBinding(
+							() -> Math.min(comboBox.getRowsCount(), comboBox.getItems().size()) * virtualFlow.getCellHeight(),
+							comboBox.rowsCountProperty(), comboBox.getItems(), virtualFlow.cellFactoryProperty(), vfInitialized
+					));
+			virtualFlow.itemsProperty().addListener((observable, oldValue, newValue) -> {
+				if (newValue != null) createBinding.run();
+			});
+			createBinding.run();
 		}
 		return virtualFlow;
 	}
@@ -274,6 +289,14 @@ public class MFXComboBoxSkin<T> extends MFXTextFieldSkin {
 	//================================================================================
 	// Overridden Methods
 	//================================================================================
+	@Override
+	protected void layoutChildren(double x, double y, double w, double h) {
+		super.layoutChildren(x, y, w, h);
+
+		if (virtualFlow != null && !vfInitialized.get() && virtualFlow.getCellHeight() != 0)
+			vfInitialized.set(true);
+	}
+
 	@Override
 	public void dispose() {
 		super.dispose();

+ 12 - 3
materialfx/src/main/java/io/github/palexdev/materialfx/skins/MFXFilterComboBoxSkin.java

@@ -22,10 +22,9 @@ import io.github.palexdev.materialfx.collections.TransformableList;
 import io.github.palexdev.materialfx.controls.BoundTextField;
 import io.github.palexdev.materialfx.controls.MFXFilterComboBox;
 import io.github.palexdev.materialfx.controls.MFXTextField;
-import io.github.palexdev.materialfx.controls.cell.MFXFilterComboBoxCell;
 import io.github.palexdev.materialfx.i18n.I18N;
-import io.github.palexdev.virtualizedfx.cell.Cell;
 import io.github.palexdev.virtualizedfx.flow.simple.SimpleVirtualFlow;
+import javafx.beans.binding.Bindings;
 import javafx.geometry.Orientation;
 import javafx.geometry.Pos;
 import javafx.scene.Node;
@@ -114,7 +113,7 @@ public class MFXFilterComboBoxSkin<T> extends MFXComboBoxSkin<T> {
 		searchField.textProperty().bindBidirectional(comboBox.searchTextProperty());
 		searchField.setMaxWidth(Double.MAX_VALUE);
 
-		SimpleVirtualFlow<T, Cell<T>> virtualFlow = new SimpleVirtualFlow<>(
+		virtualFlow = new SimpleVirtualFlow<>(
 				filterList,
 				comboBox.getCellFactory(),
 				Orientation.VERTICAL
@@ -127,6 +126,16 @@ public class MFXFilterComboBoxSkin<T> extends MFXComboBoxSkin<T> {
 			}
 		});
 
+		Runnable createBinding = () ->
+				virtualFlow.minHeightProperty().bind(Bindings.createDoubleBinding(
+						() -> Math.min(comboBox.getRowsCount(), comboBox.getItems().size()) * virtualFlow.getCellHeight(),
+						comboBox.rowsCountProperty(), comboBox.getItems(), virtualFlow.cellFactoryProperty(), vfInitialized
+				));
+		virtualFlow.itemsProperty().addListener((observable, oldValue, newValue) -> {
+			if (newValue != null) createBinding.run();
+		});
+		createBinding.run();
+
 		VBox container = new VBox(10, searchField, virtualFlow);
 		container.getStyleClass().add("search-container");
 		container.setAlignment(Pos.TOP_CENTER);