Skip to content

Commit

Permalink
Refactor FxTab - fix #45, #42
Browse files Browse the repository at this point in the history
  • Loading branch information
kamil-sita committed Jun 11, 2024
1 parent f3b82b8 commit b6bf65c
Show file tree
Hide file tree
Showing 29 changed files with 346 additions and 316 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,54 +18,43 @@
import place.sita.labelle.gui.local.fx.modulefx.FxSceneBuilderProcessors;
import place.sita.labelle.gui.local.fx.threading.ThreadingSupportSupplier;
import place.sita.labelle.gui.local.menu.Menu;
import place.sita.labelle.gui.local.tab.ApplicationTab;
import place.sita.labelle.gui.local.tab.TabRegistrar;
import place.sita.labelle.gui.local.tab.UnloadAware;

import java.util.*;

@Component
public class StageConfiguration {

private final List<ApplicationTab> applicationTabs;
private final List<TabRegistrar> tabRegistrars;
private final Menu menu;
private final ConfigurableApplicationContext applicationContext;
private final ShutdownRegistry shutdownRegistry;

private final List<ExistingStage> stages = new ArrayList<>();
private final ChildrenFactory childrenFactory;
private final UnstableSceneReporter unstableSceneReporter;

public StageConfiguration(List<ApplicationTab> applicationTabs,
List<TabRegistrar> tabRegistrars,
Menu menu,
ConfigurableApplicationContext applicationContext,
ShutdownRegistry shutdownRegistry, ChildrenFactory childrenFactory, UnstableSceneReporter unstableSceneReporter) {
this.applicationTabs = applicationTabs;
this.tabRegistrars = tabRegistrars;
this.menu = menu;

public StageConfiguration(ConfigurableApplicationContext applicationContext,
ShutdownRegistry shutdownRegistry, ChildrenFactory childrenFactory) {
this.applicationContext = applicationContext;
this.shutdownRegistry = shutdownRegistry;
this.childrenFactory = childrenFactory;
this.unstableSceneReporter = unstableSceneReporter;
}

public void configureTestStage(Stage stage) {
configureStage(stage, StageType.TEST);
public UnstableSceneReporter configureTestStage(Stage stage) {
return configureStage(stage, StageType.TEST);
}

public void configureStage(Stage stage, StageType stageType) {
public UnstableSceneReporter configureStage(Stage stage, StageType stageType) {
if (stageType != StageType.ADDITIONAL) {
System.setProperty("java.awt.headless", "false");
}

stage.setTitle("Labelle");
//TransitTheme transitTheme = new TransitTheme(com.pixelduke.transit.Style.LIGHT);
JMetro jMetro = new JMetro(Style.DARK);
FxSceneBuilderProcessors processors = new FxSceneBuilderProcessors(childrenFactory);
UnstableSceneReporter unstableSceneReporter = new UnstableSceneReporter();

FxSceneBuilderProcessors processors = new FxSceneBuilderProcessors(childrenFactory, unstableSceneReporter);
UUID loadId = UUID.randomUUID();
unstableSceneReporter.markUnstable(loadId, "Loading new stage");
Menu menu = applicationContext.getBean(Menu.class);
Node node;
try {
node = FxControllerLoader.setupForController(menu, "/fx/mainmenu.fxml", processors);
Expand All @@ -79,36 +68,6 @@ public void configureStage(Stage stage, StageType stageType) {
stage.setScene(scene);
scene.getStylesheets().add("dark_metro_labelle.css");

List<ApplicationTab> allTabs = new ArrayList<>();
for (var registrar : tabRegistrars) {
allTabs.addAll(registrar.tabs());
}
allTabs.addAll(applicationTabs);

allTabs.sort(Comparator.comparingInt(ApplicationTab::getOrder));

menu.mainTabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
new Thread(() -> {
for (var applicationTab : allTabs) {
if (applicationTab instanceof UnloadAware unloadAware) {
if (newValue != applicationTab.tab()) {
unloadAware.unload();
}
}
}
for (var applicationTab : allTabs) {
if (applicationTab instanceof UnloadAware unloadAware) {
if (newValue == applicationTab.tab()) {
unloadAware.load();
}
}
}
}).start();
});
allTabs.forEach(applicationTab -> {
menu.mainTabPane.getTabs().add(applicationTab.tab());
});

UUID id = UUID.randomUUID();
ExistingStage thisStage = new ExistingStage(id, stage);
stages.add(thisStage);
Expand All @@ -128,6 +87,8 @@ public void handle(WindowEvent t) {
}
});
}

return unstableSceneReporter;
}

public enum StageType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rtextarea.RTextScrollPane;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import place.sita.modulefx.annotations.FxTab;
import place.sita.modulefx.annotations.PostFxConstruct;

import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;

@Scope(scopeName = SCOPE_PROTOTYPE)
@Component
@FxTab(resourceFile = "/fx/automation.fxml", order = 5, tabName = "Automation")
public class AutomationTab {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class UnstableSceneReporter {

private static final Logger log = LoggerFactory.getLogger(UnstableSceneReporter.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package place.sita.labelle.gui.local.fx.modulefx;

import java.util.List;

public interface ChildrenFactory {

<T> T create(Class<T> clazz);

<T> List<Class<?>> getClasses(Class<T> clazz);

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
package place.sita.labelle.gui.local.fx.modulefx;

import javafx.scene.Node;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import place.sita.labelle.gui.local.fx.UnstableSceneReporter;

import java.util.UUID;

public class FxControllerLoader {

Expand Down Expand Up @@ -43,8 +38,8 @@ public FxSceneBuilderProcessors processors() {
}

@Override
public Node setupForController(Object bean, Object parentController, Node parentNode, String resource, FxSetupContext context) {
return internalSetupForController(bean, parentController, parentNode, resource, context.processors());
public Node setupForController(Object bean, String resource, FxSetupContext context) {
return internalSetupForController(bean, controller, results, resource, context.processors());
}
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package place.sita.labelle.gui.local.fx.modulefx;

import place.sita.labelle.gui.local.fx.modulefx.processors.CheckSetHeightCorrelationProcessor;
import place.sita.labelle.gui.local.fx.modulefx.processors.InjectChildrenProcessor;
import place.sita.labelle.gui.local.fx.modulefx.processors.InjectParentFieldProcessor;
import place.sita.labelle.gui.local.fx.modulefx.processors.PostFxInjectProcessor;
import place.sita.labelle.gui.local.fx.UnstableSceneReporter;
import place.sita.labelle.gui.local.fx.modulefx.processors.*;
import place.sita.labelle.gui.local.fx.modulefx.processors.tabs.InjectTabsProcessor;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -12,10 +11,11 @@ public class FxSceneBuilderProcessors {

private final List<FxSceneBuilderProcessor> processors = new ArrayList<>();

public FxSceneBuilderProcessors(ChildrenFactory childrenFactory) {
public FxSceneBuilderProcessors(ChildrenFactory childrenFactory, UnstableSceneReporter unstableSceneReporter) {
processors.add(new CheckSetHeightCorrelationProcessor());
processors.add(new InjectParentFieldProcessor());
processors.add(new InjectChildrenProcessor(childrenFactory));
processors.add(new InjectTabsProcessor(childrenFactory, unstableSceneReporter));
processors.add(new PostFxInjectProcessor());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ public interface FxSetupContext {

FxSceneBuilderProcessors processors();

Node setupForController(Object bean, Object parentController, Node parentNode, String resource, FxSetupContext context);
Node setupForController(Object bean, String resource, FxSetupContext context);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package place.sita.labelle.gui.local.fx.modulefx;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class SpringChildrenFactory implements ChildrenFactory {

Expand All @@ -16,4 +22,32 @@ public SpringChildrenFactory(ApplicationContext context) {
public <T> T create(Class<T> clazz) {
return context.getBean(clazz);
}

@Override
public <T> List<Class<?>> getClasses(Class<T> clazz) {
ClassPathScanningCandidateComponentProvider provider =
new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(clazz));

List<Class<?>> classes = new ArrayList<>();

for (BeanDefinition beanDef : provider.findCandidateComponents("place.sita.labelle")) {
try {
// let's hope that this is the actual class, and not something else.
// as it doesn't have to be, see javadoc
Class<?> beanClass = Class.forName(beanDef.getBeanClassName());
classes.add(beanClass);
} catch (ClassNotFoundException e) {
throw new LoadClassesException(e);
}
}

return classes;
}

private static class LoadClassesException extends RuntimeException {
public LoadClassesException(Exception e) {
super(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ private void injectChild(Object parentController, Field fieldWithAnnotation, Cla

String resource = classType.getAnnotation(FxNode.class).resourceFile();
Object bean = childrenFactory.create(classType);
Node node = context.setupForController(bean, parentController, parentNode, resource, context);
Node node = context.setupForController(bean, resource, context);
fieldWithAnnotation.setAccessible(true);
fieldWithAnnotation.set(parentController, bean);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package place.sita.labelle.gui.local.fx.modulefx.processors.tabs;

import javafx.scene.control.Tab;
import place.sita.labelle.gui.local.fx.UnstableSceneReporter;

public interface FxSmartTab {

Tab tab();

void load(UnstableSceneReporter unstableSceneReporter);

void unload();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package place.sita.labelle.gui.local.fx.modulefx.processors.tabs;

import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Tab;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Region;
import place.sita.labelle.gui.local.fx.UnstableSceneReporter;
import place.sita.labelle.gui.local.fx.modulefx.ChildrenFactory;
import place.sita.labelle.gui.local.fx.modulefx.FxSetupContext;
import place.sita.modulefx.annotations.FxTab;

import java.util.UUID;

public class FxSmartTabFactory {

public static FxSmartTab create(FxTab fxTab, Class<?> tabClass, FxSetupContext setupContext, ChildrenFactory factory) {
switch (fxTab.loadMode()) {
case ONLY_WHEN_NEEDED:
return createUnloadingTab(fxTab, tabClass, setupContext, factory);
default:
throw new IllegalArgumentException("Unknown load mode: " + fxTab.loadMode());
}
}

private static FxSmartTab createUnloadingTab(FxTab fxTab, Class<?> tabClass, FxSetupContext setupContext, ChildrenFactory factory) {
UUID id = UUID.randomUUID();
String stringId = id.toString();

Tab internalTab = new Tab(fxTab.tabName());
internalTab.setId(stringId);
internalTab.setClosable(false);

Platform.runLater(() -> {
internalTab.setContent(new ProgressIndicator(-1));
});

return new FxSmartTab() {
private boolean loaded = false;
@Override
public Tab tab() {
return internalTab;
}

@Override
public void load(UnstableSceneReporter unstableSceneReporter) {
if (loaded) {
return;
}

UUID loadId = UUID.randomUUID();
unstableSceneReporter.markUnstable(loadId, "Loading tab: " + tabClass.getName());

Object bean = factory.create(tabClass);
Node component = setupContext.setupForController(bean, fxTab.resourceFile(), setupContext);

AnchorPane anchorPane = new AnchorPane();
if (component instanceof Region region) {
region.setMinWidth(100);
region.setMinHeight(100);
}
anchorPane.getChildren().add(component);
AnchorPane.setTopAnchor(component, 0.0);
AnchorPane.setLeftAnchor(component, 0.0);
AnchorPane.setRightAnchor(component, 0.0);
AnchorPane.setBottomAnchor(component, 0.0);
Platform.runLater(() -> {
internalTab.setContent(anchorPane);
unstableSceneReporter.markStable(loadId);
});
loaded = true;
}

@Override
public void unload() {
if (!loaded) {
return;
}

Platform.runLater(() -> {
internalTab.setContent(new ProgressIndicator(-1));
});

loaded = false;
}
};
}

}
Loading

0 comments on commit b6bf65c

Please sign in to comment.