Binding and FxmlComponent controls to allow bindings and loading of FXML Components.
This commit is contained in:
parent
be6a8c853e
commit
2b60038774
15
fx/ideas.md
Normal file
15
fx/ideas.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Ideen
|
||||||
|
|
||||||
|
# Bindings
|
||||||
|
Bindngs kommen über ein spezielles Binding Control, das dann notwendige Bindings beinhaltet.
|
||||||
|
|
||||||
|
Da kann dann auch eine eigene Logik zur Erkennung des Bindings erfolgen oder zusätziche Informationen bezüglich notwendiger Elemente in dem ViewModel
|
||||||
|
|
||||||
|
# FXMLComponent
|
||||||
|
Dient dem Laden einer Komponente und bekommt dazu das fxml, die Daten und ggf. auch eine ModelView.
|
||||||
|
|
||||||
|
# ModelView generieren
|
||||||
|
Damit eine ModelView nicht ständig manuell generiert werden muss, ist hier ggf. etwas zu generieren?
|
||||||
|
Ggf. eine eigenes Beschreibungssprache?
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
package de.neitzel.fx.component.controls;
|
||||||
|
|
||||||
|
import de.neitzel.fx.component.model.BindingData;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The BindingControl class represents a UI control that manages a list
|
||||||
|
* of {@link BindingData} objects. It extends the {@link Region} class and
|
||||||
|
* provides functionality to bind and monitor connections between source
|
||||||
|
* and target properties.
|
||||||
|
*
|
||||||
|
* The primary purpose of this control is to maintain an observable list
|
||||||
|
* of bindings, allowing developers to track or adjust the linked properties
|
||||||
|
* dynamically.
|
||||||
|
*
|
||||||
|
* The internal list of bindings is implemented as an {@link ObservableList},
|
||||||
|
* allowing property change notifications to be easily monitored for UI
|
||||||
|
* updates or other reactive behaviors.
|
||||||
|
*
|
||||||
|
* This class serves as an organizational component and does not provide
|
||||||
|
* any user interaction by default.
|
||||||
|
*/
|
||||||
|
public class Binding extends Region {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an observable list of {@link BindingData} objects contained within the
|
||||||
|
* {@link Binding} instance. This list is utilized to manage and monitor
|
||||||
|
* the bindings between source and target properties dynamically.
|
||||||
|
*
|
||||||
|
* The list is implemented as an {@link ObservableList}, allowing changes in the
|
||||||
|
* collection to be observed and reacted to, such as triggering UI updates or
|
||||||
|
* responding to binding modifications.
|
||||||
|
*
|
||||||
|
* This field is initialized as an empty list using {@link FXCollections#observableArrayList()}.
|
||||||
|
* It is declared as final to ensure its reference cannot be changed, while the
|
||||||
|
* contents of the list remain mutable.
|
||||||
|
*/
|
||||||
|
private final ObservableList<BindingData> bindings = FXCollections.observableArrayList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the observable list of {@code Binding} objects associated with this control.
|
||||||
|
* The returned list allows monitoring and management of the bindings maintained
|
||||||
|
* by the {@code BindingControl}.
|
||||||
|
*
|
||||||
|
* @return an {@code ObservableList<Binding>} containing the bindings managed by this control
|
||||||
|
*/
|
||||||
|
public ObservableList<BindingData> getBindings() {
|
||||||
|
return bindings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new instance of the BindingControl class.
|
||||||
|
*
|
||||||
|
* This default constructor initializes the BindingControl without
|
||||||
|
* any pre-configured bindings. The instance will contain an empty
|
||||||
|
* {@link ObservableList} of {@link BindingData} objects, which can later
|
||||||
|
* be populated as needed.
|
||||||
|
*
|
||||||
|
* The constructor does not perform additional setup or initialization,
|
||||||
|
* allowing the class to be extended or customized as necessary.
|
||||||
|
*/
|
||||||
|
public Binding() {
|
||||||
|
// Absichtlich leer – wird später "ausgewertet"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
package de.neitzel.fx.component.controls;
|
||||||
|
|
||||||
|
import de.neitzel.fx.component.ComponentLoader;
|
||||||
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.Parent;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class FxmlComponent extends StackPane {
|
||||||
|
|
||||||
|
private final StringProperty fxml = new SimpleStringProperty();
|
||||||
|
private final StringProperty direction = new SimpleStringProperty("unidirectional");
|
||||||
|
private final ObjectProperty<Object> data = new SimpleObjectProperty<>();
|
||||||
|
|
||||||
|
public StringProperty fxmlProperty() { return fxml; }
|
||||||
|
public String getFxml() { return fxml.get(); }
|
||||||
|
public void setFxml(String fxml) { this.fxml.set(fxml); }
|
||||||
|
|
||||||
|
public StringProperty directionProperty() { return direction; }
|
||||||
|
public String getDirection() { return direction.get(); }
|
||||||
|
public void setDirection(String direction) { this.direction.set(direction); }
|
||||||
|
|
||||||
|
public ObjectProperty<Object> dataProperty() { return data; }
|
||||||
|
public Object getData() { return data.get(); }
|
||||||
|
public void setData(Object data) { this.data.set(data); }
|
||||||
|
|
||||||
|
public FxmlComponent() {
|
||||||
|
fxml.addListener((obs, oldVal, newVal) -> load());
|
||||||
|
data.addListener((obs, oldVal, newVal) -> injectData());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void load() {
|
||||||
|
if (getFxml() == null || getFxml().isBlank()) return;
|
||||||
|
try {
|
||||||
|
ComponentLoader loader = new ComponentLoader();
|
||||||
|
// Option: ControllerFactory verwenden, wenn nötig
|
||||||
|
Parent content = loader.load(getClass().getResource(getFxml()));
|
||||||
|
|
||||||
|
getChildren().setAll(content);
|
||||||
|
|
||||||
|
Object controller = loader.getController();
|
||||||
|
if (controller != null && getData() != null) {
|
||||||
|
injectDataToController(controller, getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void injectData() {
|
||||||
|
if (!getChildren().isEmpty() && getData() != null) {
|
||||||
|
Object controller = getControllerFromChild(getChildren().get(0));
|
||||||
|
if (controller != null) {
|
||||||
|
injectDataToController(controller, getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void injectDataToController(Object controller, Object dataObject) {
|
||||||
|
// Daten-Objekt per Reflection zuweisen
|
||||||
|
// Beispiel: Controller hat `setData(User data)`
|
||||||
|
Arrays.stream(controller.getClass().getMethods())
|
||||||
|
.filter(m -> m.getName().equals("setData") && m.getParameterCount() == 1)
|
||||||
|
.findFirst()
|
||||||
|
.ifPresent(method -> {
|
||||||
|
try {
|
||||||
|
method.invoke(controller, dataObject);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Optional: automatisch Binding ausführen (s. u.)
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getControllerFromChild(Node node) {
|
||||||
|
if (node.getProperties().containsKey("fx:controller")) {
|
||||||
|
return node.getProperties().get("fx:controller");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
package de.neitzel.fx.component.model;
|
||||||
|
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Binding class represents a connection between a source and a target,
|
||||||
|
* with an associated direction. It is typically used to define a binding
|
||||||
|
* relationship that determines how data flows between these two entities.
|
||||||
|
*
|
||||||
|
* The class provides three properties:
|
||||||
|
* - direction: Represents the type of the binding. Defaults to "unidirectional".
|
||||||
|
* - source: Represents the source of the binding.
|
||||||
|
* - target: Represents the target of the binding.
|
||||||
|
*
|
||||||
|
* It uses JavaFX property types, allowing these properties to be observed
|
||||||
|
* for changes.
|
||||||
|
*/
|
||||||
|
public class BindingData {
|
||||||
|
/**
|
||||||
|
* Represents the direction of the binding in the {@code Binding} class.
|
||||||
|
* It determines whether the binding is unidirectional or bidirectional.
|
||||||
|
* The default value is "unidirectional".
|
||||||
|
*
|
||||||
|
* This property is observed for changes, enabling dynamic updates
|
||||||
|
* within the JavaFX property system.
|
||||||
|
*/
|
||||||
|
private StringProperty direction = new SimpleStringProperty("unidirectional");
|
||||||
|
/**
|
||||||
|
* Represents the source of the binding. This property holds a string value
|
||||||
|
* that specifies the originating object or identifier in the binding connection.
|
||||||
|
* It can be observed for changes, allowing updates to the binding relationship
|
||||||
|
* when the source value is modified.
|
||||||
|
*/
|
||||||
|
private StringProperty source = new SimpleStringProperty();
|
||||||
|
/**
|
||||||
|
* Represents the target of the binding in the Binding class.
|
||||||
|
* This property holds the target value, which can be observed for changes.
|
||||||
|
*/
|
||||||
|
private StringProperty target = new SimpleStringProperty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current direction of the binding.
|
||||||
|
* The direction determines how data flows between
|
||||||
|
* the source and the target, and typically defaults to "unidirectional".
|
||||||
|
*
|
||||||
|
* @return the current direction of the binding
|
||||||
|
*/
|
||||||
|
public String getDirection() { return direction.get(); }
|
||||||
|
/**
|
||||||
|
* Sets the direction of the binding.
|
||||||
|
*
|
||||||
|
* @param dir the new direction to set for the binding
|
||||||
|
*/
|
||||||
|
public void setDirection(String dir) { direction.set(dir); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current source value of the binding.
|
||||||
|
*
|
||||||
|
* @return the source value as a String.
|
||||||
|
*/
|
||||||
|
public String getSource() { return source.get(); }
|
||||||
|
/**
|
||||||
|
* Sets the value of the source property for this binding.
|
||||||
|
*
|
||||||
|
* @param source the new source value to be set
|
||||||
|
*/
|
||||||
|
public void setSource(String source) { this.source.set(source); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the current value of the target property.
|
||||||
|
*
|
||||||
|
* @return the value of the target property as a String.
|
||||||
|
*/
|
||||||
|
public String getTarget() { return target.get(); }
|
||||||
|
/**
|
||||||
|
* Sets the target property of the binding.
|
||||||
|
*
|
||||||
|
* @param target the new value to set for the target property
|
||||||
|
*/
|
||||||
|
public void setTarget(String target) { this.target.set(target); }
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user