Skip to content

Commit 5ba4cea

Browse files
committed
Add component
1 parent 8fa6deb commit 5ba4cea

31 files changed

+789
-732
lines changed

README.md

Lines changed: 150 additions & 112 deletions
Large diffs are not rendered by default.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright 2024-2025 Pavel Castornii.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.techsenger.mvvm4fx.core;
18+
19+
import javafx.beans.property.ReadOnlyObjectProperty;
20+
import javafx.beans.property.ReadOnlyObjectWrapper;
21+
22+
/**
23+
*
24+
* @author Pavel Castornii
25+
*/
26+
public abstract class AbstractChildComponent<T extends AbstractChildView<?>> extends AbstractParentComponent<T>
27+
implements ChildComponent<T> {
28+
29+
protected abstract class Mediator extends AbstractParentComponent.Mediator implements ChildMediator {
30+
31+
private final ReadOnlyObjectWrapper<ParentViewModel> parent = new ReadOnlyObjectWrapper<>();
32+
33+
public Mediator() {
34+
AbstractChildComponent.this.parent.addListener((ov, oldV, newV) -> {
35+
if (newV == null) {
36+
this.parent.set(null);
37+
} else {
38+
this.parent.set(newV.getView().getViewModel());
39+
}
40+
});
41+
}
42+
43+
@Override
44+
public ReadOnlyObjectProperty<ParentViewModel> parentProperty() {
45+
return this.parent.getReadOnlyProperty();
46+
}
47+
48+
@Override
49+
public ParentViewModel getParent() {
50+
return this.parent.get();
51+
}
52+
}
53+
54+
private final ReadOnlyObjectWrapper<ParentComponent<?>> parent = new ReadOnlyObjectWrapper<>();
55+
56+
public AbstractChildComponent(T view) {
57+
super(view);
58+
}
59+
60+
@Override
61+
public ReadOnlyObjectProperty<ParentComponent<?>> parentProperty() {
62+
return this.parent.getReadOnlyProperty();
63+
}
64+
65+
@Override
66+
public ParentComponent<?> getParent() {
67+
return this.parent.get();
68+
}
69+
70+
/**
71+
* Sets the parent component for this component.
72+
* <p>
73+
* This method is normally called automatically when the component is added as a child to another component.
74+
* It can also be used explicitly when only the child-to-parent relationship needs to be established, without
75+
* adding the component to the parent's list of children.
76+
*
77+
* @param parent the parent component to set
78+
*/
79+
protected void setParent(ParentComponent<?> parent) {
80+
this.parent.set(parent);
81+
}
82+
83+
@Override
84+
protected abstract AbstractParentComponent.Mediator createMediator();
85+
}

mvvm4fx-core/src/main/java/com/techsenger/mvvm4fx/core/AbstractChildView.java

Lines changed: 2 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,64 +16,24 @@
1616

1717
package com.techsenger.mvvm4fx.core;
1818

19-
import javafx.beans.property.ReadOnlyObjectProperty;
20-
import javafx.beans.property.ReadOnlyObjectWrapper;
21-
2219
/**
2320
*
2421
* @author Pavel Castornii
2522
*/
2623
public abstract class AbstractChildView<T extends AbstractChildViewModel> extends AbstractParentView<T>
2724
implements ChildView<T> {
2825

29-
private final ReadOnlyObjectWrapper<ParentView<?>> parent = new ReadOnlyObjectWrapper<>();
30-
3126
public AbstractChildView(T viewModel) {
3227
super(viewModel);
3328
}
3429

3530
@Override
36-
public ReadOnlyObjectProperty<ParentView<?>> parentProperty() {
37-
return this.parent.getReadOnlyProperty();
38-
}
39-
40-
@Override
41-
public ParentView<?> getParent() {
42-
return this.parent.get();
43-
}
44-
45-
@Override
46-
public ChildComposer<?> getComposer() {
47-
return (ChildComposer<?>) super.getComposer();
31+
public AbstractChildComponent<?> getComponent() {
32+
return (AbstractChildComponent<?>) super.getComponent();
4833
}
4934

5035
@Override
5136
protected void addListeners(T viewModel) {
5237
super.addListeners(viewModel);
53-
parent.addListener((ov, oldV, newV) -> {
54-
if (newV == null) {
55-
viewModel.parentWrapper().set(null);
56-
} else {
57-
viewModel.parentWrapper().set(newV.getViewModel());
58-
}
59-
});
60-
}
61-
62-
@Override
63-
protected ChildComposer<?> createComposer() {
64-
return (ChildComposer<?>) super.createComposer();
65-
}
66-
67-
/**
68-
* Sets the parent component for this component.
69-
* <p>
70-
* This method is normally called automatically when the component is added as a child to another component.
71-
* It can also be used explicitly when only the child-to-parent relationship needs to be established, without
72-
* adding the component to the parent's list of children.
73-
*
74-
* @param parent the parent component to set
75-
*/
76-
protected void setParent(ParentView<?> parent) {
77-
this.parent.set(parent);
7838
}
7939
}

mvvm4fx-core/src/main/java/com/techsenger/mvvm4fx/core/AbstractChildViewModel.java

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,18 @@
1616

1717
package com.techsenger.mvvm4fx.core;
1818

19-
import javafx.beans.property.ReadOnlyObjectProperty;
20-
import javafx.beans.property.ReadOnlyObjectWrapper;
21-
2219
/**
2320
*
2421
* @author Pavel Castornii
2522
*/
2623
public abstract class AbstractChildViewModel extends AbstractParentViewModel implements ChildViewModel {
2724

28-
private final ReadOnlyObjectWrapper<ParentViewModel> parent = new ReadOnlyObjectWrapper<>();
29-
3025
public AbstractChildViewModel() {
3126
super();
3227
}
3328

34-
@Override
35-
public ReadOnlyObjectProperty<ParentViewModel> parentProperty() {
36-
return this.parent.getReadOnlyProperty();
37-
}
38-
39-
@Override
40-
public ParentViewModel getParent() {
41-
return this.parent.get();
42-
}
43-
4429
@Override
4530
public ChildMediator getMediator() {
4631
return (ChildMediator) super.getMediator();
4732
}
48-
49-
ReadOnlyObjectWrapper<ParentViewModel> parentWrapper() {
50-
return parent;
51-
}
5233
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright 2024-2025 Pavel Castornii.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.techsenger.mvvm4fx.core;
18+
19+
import org.slf4j.Logger;
20+
import org.slf4j.LoggerFactory;
21+
22+
/**
23+
*
24+
* @author Pavel Castornii
25+
*/
26+
public abstract class AbstractComponent<T extends AbstractComponentView<?>> implements Component<T> {
27+
28+
private static final Logger logger = LoggerFactory.getLogger(AbstractComponent.class);
29+
30+
protected abstract class Mediator implements ComponentMediator {
31+
32+
}
33+
34+
private final T view;
35+
36+
public AbstractComponent(T view) {
37+
this.view = view;
38+
this.view.setComponent(this);
39+
}
40+
41+
@Override
42+
public T getView() {
43+
return view;
44+
}
45+
46+
@Override
47+
public final void initialize() {
48+
var viewModel = this.view.getViewModel();
49+
var descriptor = viewModel.getDescriptor();
50+
try {
51+
var currentState = descriptor.getState();
52+
if (currentState != ComponentState.CREATING) {
53+
throw new IllegalStateException("Unexpected state of the component - " + currentState.name());
54+
}
55+
// pre-initialization
56+
preInitialize();
57+
// initialization
58+
descriptor.getStateWrapper().set(ComponentState.INITIALIZING);
59+
viewModel.initialize();
60+
this.view.initialize();
61+
descriptor.getStateWrapper().set(ComponentState.INITIALIZED);
62+
logger.debug("{} Initialized component", descriptor.getLogPrefix());
63+
// post-initialization
64+
postInitialize();
65+
} catch (Exception ex) {
66+
logger.error("{} Error initializing", descriptor.getLogPrefix(), ex);
67+
}
68+
}
69+
70+
@Override
71+
public final void deinitialize() {
72+
var viewModel = this.view.getViewModel();
73+
var descriptor = viewModel.getDescriptor();
74+
try {
75+
var currentState = descriptor.getState();
76+
if (currentState != ComponentState.INITIALIZED) {
77+
throw new IllegalStateException("Unexpected state of the component - " + currentState.name());
78+
}
79+
// pre-deinitialization
80+
preDeinitialize();
81+
// deinitialization
82+
descriptor.getStateWrapper().set(ComponentState.DEINITIALIZING);
83+
this.view.deinitialize();
84+
viewModel.deinitialize();
85+
descriptor.getStateWrapper().set(ComponentState.DEINITIALIZED);
86+
logger.debug("{} Deinitialized component", descriptor.getLogPrefix());
87+
// post-deinitialization
88+
postDeinitialize();
89+
} catch (Exception ex) {
90+
logger.error("{} Error deinitializing", descriptor.getLogPrefix(), ex);
91+
}
92+
}
93+
94+
/**
95+
* The first method called in initialization.
96+
*/
97+
protected void preInitialize() {
98+
var mediator = createMediator();
99+
this.view.getViewModel().setMediator(mediator);
100+
this.view.getViewModel().restoreHistory();
101+
}
102+
103+
/**
104+
* The last method called in initialization.
105+
*/
106+
protected void postInitialize() { }
107+
108+
/**
109+
* The first method called in deinitialization.
110+
*/
111+
protected void preDeinitialize() { }
112+
113+
/**
114+
* The last method called in deinitialization.
115+
*/
116+
protected void postDeinitialize() {
117+
this.view.getViewModel().saveHistory();
118+
}
119+
120+
protected abstract AbstractComponent.Mediator createMediator();
121+
}

0 commit comments

Comments
 (0)